[backend/masto-client] Add user notes endpoint

This commit is contained in:
Laura Hausmann 2024-02-06 22:10:15 +01:00
parent 68d5d907fe
commit 61ba7b543e
No known key found for this signature in database
GPG key ID: D044E84C5BE01605
3 changed files with 76 additions and 42 deletions

View file

@ -1,16 +1,16 @@
using Iceshrimp.Backend.Controllers.Attributes;
using Iceshrimp.Backend.Controllers.Mastodon.Attributes;
using Iceshrimp.Backend.Controllers.Mastodon.Schemas;
using Iceshrimp.Backend.Controllers.Mastodon.Schemas.Entities;
using Iceshrimp.Backend.Core.Database;
using Iceshrimp.Backend.Core.Database.Tables;
using Iceshrimp.Backend.Core.Extensions;
using Iceshrimp.Backend.Core.Federation.ActivityPub;
using Iceshrimp.Backend.Core.Helpers;
using Iceshrimp.Backend.Core.Middleware;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.EntityFrameworkCore;
using MastodonUserRenderer = Iceshrimp.Backend.Controllers.Mastodon.Renderers.UserRenderer;
using Iceshrimp.Backend.Controllers.Mastodon.Renderers;
namespace Iceshrimp.Backend.Controllers.Mastodon;
@ -21,10 +21,10 @@ namespace Iceshrimp.Backend.Controllers.Mastodon;
[Produces("application/json")]
public class MastodonAccountController(
DatabaseContext db,
MastodonUserRenderer userRenderer,
ActivityRenderer activityRenderer,
UserRenderer apUserRenderer,
ActivityDeliverService deliverSvc
UserRenderer userRenderer,
NoteRenderer noteRenderer,
ActivityPub.ActivityRenderer activityRenderer,
ActivityPub.ActivityDeliverService deliverSvc
) : Controller {
[HttpGet("verify_credentials")]
[Authorize("read:accounts")]
@ -134,42 +134,6 @@ public class MastodonAccountController(
return Ok(res);
}
[HttpGet("relationships")]
[Authorize("read:follows")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Relationship[]))]
[ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(MastodonErrorResponse))]
[ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> GetRelationships([FromQuery(Name = "id")] List<string> ids) {
var user = HttpContext.GetUser() ?? throw new GracefulException("Failed to get user from HttpContext");
if (ids.Contains(user.Id))
throw GracefulException.BadRequest("You cannot request relationship status with yourself");
var users = await db.Users.IncludeCommonProperties()
.Where(p => ids.Contains(p.Id))
.PrecomputeRelationshipData(user)
.ToListAsync();
var res = users.Select(u => new Relationship {
Id = u.Id,
Following = u.PrecomputedIsFollowedBy ?? false,
FollowedBy = u.PrecomputedIsFollowing ?? false,
Blocking = u.PrecomputedIsBlockedBy ?? false,
BlockedBy = u.PrecomputedIsBlocking ?? false,
Requested = u.PrecomputedIsRequestedBy ?? false,
RequestedBy = u.PrecomputedIsRequested ?? false,
Muting = u.PrecomputedIsMutedBy ?? false,
Endorsed = false, //FIXME
Note = "", //FIXME
Notifying = false, //FIXME
DomainBlocking = false, //FIXME
MutingNotifications = false, //FIXME
ShowingReblogs = true //FIXME
});
return Ok(res);
}
[HttpPost("{id}/unfollow")]
[Authorize("write:follows")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Relationship))]
@ -222,4 +186,62 @@ public class MastodonAccountController(
return Ok(res);
}
[HttpGet("relationships")]
[Authorize("read:follows")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(Relationship[]))]
[ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(MastodonErrorResponse))]
[ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> GetRelationships([FromQuery(Name = "id")] List<string> ids) {
var user = HttpContext.GetUser() ?? throw new GracefulException("Failed to get user from HttpContext");
if (ids.Contains(user.Id))
throw GracefulException.BadRequest("You cannot request relationship status with yourself");
var users = await db.Users.IncludeCommonProperties()
.Where(p => ids.Contains(p.Id))
.PrecomputeRelationshipData(user)
.ToListAsync();
var res = users.Select(u => new Relationship {
Id = u.Id,
Following = u.PrecomputedIsFollowedBy ?? false,
FollowedBy = u.PrecomputedIsFollowing ?? false,
Blocking = u.PrecomputedIsBlockedBy ?? false,
BlockedBy = u.PrecomputedIsBlocking ?? false,
Requested = u.PrecomputedIsRequestedBy ?? false,
RequestedBy = u.PrecomputedIsRequested ?? false,
Muting = u.PrecomputedIsMutedBy ?? false,
Endorsed = false, //FIXME
Note = "", //FIXME
Notifying = false, //FIXME
DomainBlocking = false, //FIXME
MutingNotifications = false, //FIXME
ShowingReblogs = true //FIXME
});
return Ok(res);
}
[HttpGet("{id}/statuses")]
[Authorize("read:statuses")]
[LinkPagination(20, 40)]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(IEnumerable<Status>))]
[ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(MastodonErrorResponse))]
[ProducesResponseType(StatusCodes.Status403Forbidden, Type = typeof(MastodonErrorResponse))]
public async Task<IActionResult> GetHomeTimeline(string id, PaginationQuery query) {
//TODO: there's a lot more query params to implement here
var user = HttpContext.GetUser() ?? throw new GracefulException("Failed to get user from HttpContext");
var res = await db.Notes
.IncludeCommonProperties()
.FilterByUser(id)
.EnsureVisibleFor(user)
.Paginate(query, ControllerContext)
.PrecomputeVisibilities(user)
.RenderAllForMastodonAsync(noteRenderer);
return Ok(res);
}
}

View file

@ -76,6 +76,14 @@ public static class NoteQueryableExtensions {
return query.Where(note => note.User == user || note.User.IsFollowedBy(user));
}
public static IQueryable<Note> FilterByUser(this IQueryable<Note> query, User user) {
return query.Where(note => note.User == user);
}
public static IQueryable<Note> FilterByUser(this IQueryable<Note> query, string userId) {
return query.Where(note => note.UserId == userId);
}
public static IQueryable<Note> EnsureVisibleFor(this IQueryable<Note> query, User? user) {
if (user == null)
return query.Where(note => note.VisibilityIsPublicOrHome)

View file

@ -47,4 +47,8 @@
<Content Include="wwwroot\.vite\manifest.json" CopyToPublishDirectory="PreserveNewest"/>
</ItemGroup>
<ItemGroup>
<None Remove="migrate.sql" />
</ItemGroup>
</Project>