femto-backend/Femto.Api/Controllers/Posts/PostsController.cs
2025-08-10 21:21:40 +02:00

154 lines
4.5 KiB
C#

using Femto.Api.Controllers.Posts.Dto;
using Femto.Common;
using Femto.Modules.Blog.Application;
using Femto.Modules.Blog.Application.Commands.AddPostComment;
using Femto.Modules.Blog.Application.Commands.AddPostReaction;
using Femto.Modules.Blog.Application.Commands.ClearPostReaction;
using Femto.Modules.Blog.Application.Commands.CreatePost;
using Femto.Modules.Blog.Application.Commands.DeletePost;
using Femto.Modules.Blog.Application.Queries.GetPosts;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace Femto.Api.Controllers.Posts;
[ApiController]
[Route("posts")]
public class PostsController(IBlogModule blogModule, ICurrentUserContext currentUserContext, IAuthorizationService auth)
: ControllerBase
{
[HttpGet]
public async Task<ActionResult<LoadPostsResponse>> LoadPosts(
[FromQuery] GetPublicPostsSearchParams searchParams,
CancellationToken cancellationToken
)
{
var res = await blogModule.Query(
new GetPostsQuery(currentUserContext.CurrentUser?.Id)
{
After = searchParams.After,
Amount = searchParams.Amount ?? 20,
AuthorId = searchParams.AuthorId,
Author = searchParams.Author,
},
cancellationToken
);
return new LoadPostsResponse(res.Posts.Select(PostDto.FromModel));
}
[HttpPost]
[Authorize]
public async Task<ActionResult<CreatePostResponse>> CreatePost(
[FromBody] CreatePostRequest req,
CancellationToken cancellationToken
)
{
var post = await blogModule.Command(
new CreatePostCommand(
req.AuthorId,
req.Content,
req.Media.Select(
(media, idx) =>
new CreatePostMedia(
media.MediaId,
media.Url,
media.Type,
idx,
media.Width,
media.Height
)
),
req.IsPublic,
currentUserContext.CurrentUser!
),
cancellationToken
);
return new CreatePostResponse(PostDto.FromModel(post));
}
[HttpGet("{postId}")]
public async Task<ActionResult<GetPostResponse>> GetPost(
Guid postId,
CancellationToken cancellationToken
)
{
var result = await blogModule.Query(
new GetPostsQuery(postId, currentUserContext.CurrentUser?.Id),
cancellationToken
);
var post = result.Posts.SingleOrDefault();
if (post is null)
return NotFound();
return new GetPostResponse(PostDto.FromModel(post));
}
[HttpDelete("{postId}")]
[Authorize]
public async Task DeletePost(Guid postId, CancellationToken cancellationToken)
{
await blogModule.Command(
new DeletePostCommand(postId, currentUserContext.CurrentUser!.Id),
cancellationToken
);
}
[HttpPost("{postId}/reactions")]
[Authorize]
public async Task<ActionResult> AddPostReaction(
Guid postId,
[FromBody] AddPostReactionRequest request,
CancellationToken cancellationToken
)
{
var currentUser = currentUserContext.CurrentUser!;
await blogModule.Command(
new AddPostReactionCommand(postId, request.Emoji, currentUser.Id),
cancellationToken
);
return this.Ok();
}
[HttpDelete("{postId}/reactions")]
[Authorize]
public async Task<ActionResult> DeletePostReaction(
Guid postId,
[FromBody] DeletePostReactionRequest request,
CancellationToken cancellationToken
)
{
var currentUser = currentUserContext.CurrentUser!;
await blogModule.Command(
new ClearPostReactionCommand(postId, request.Emoji, currentUser.Id),
cancellationToken
);
return this.Ok();
}
[HttpPost("{postId}/comments")]
[Authorize]
public async Task<ActionResult> AddPostComment(
Guid postId,
[FromBody] AddPostCommentRequest request,
CancellationToken cancellationToken
)
{
if (currentUserContext.CurrentUser?.Id != request.AuthorId)
return this.BadRequest();
await blogModule.Command(
new AddPostCommentCommand(postId, request.AuthorId, request.Content),
cancellationToken
);
return this.Ok();
}
}