diff --git a/BlogPlatform/BlogPlatform.csproj b/BlogPlatform/BlogPlatform.csproj index 15a03ab..eefd7b6 100644 --- a/BlogPlatform/BlogPlatform.csproj +++ b/BlogPlatform/BlogPlatform.csproj @@ -18,13 +18,12 @@ + - - diff --git a/BlogPlatform/DTO/Comment/Response/GetCommentDto.cs b/BlogPlatform/DTO/Comment/Response/GetCommentDto.cs index e341d71..9170bad 100644 --- a/BlogPlatform/DTO/Comment/Response/GetCommentDto.cs +++ b/BlogPlatform/DTO/Comment/Response/GetCommentDto.cs @@ -5,6 +5,6 @@ public class GetCommentDto public int Id { get; set; } public string? Content { get; set; } public DateOnly CreatedAt { get; set; } - public int PostId { get; set; } + public int? PostId { get; set; } public int UserId { get; set; } } \ No newline at end of file diff --git a/BlogPlatform/DTO/Post/Request/PatchPostDecrementLikeDto.cs b/BlogPlatform/DTO/Post/Request/PatchPostDecrementLikeDto.cs index 07cab01..2c53f7e 100644 --- a/BlogPlatform/DTO/Post/Request/PatchPostDecrementLikeDto.cs +++ b/BlogPlatform/DTO/Post/Request/PatchPostDecrementLikeDto.cs @@ -3,5 +3,4 @@ namespace BlogPlatform.DTO.Post.Request; public class PatchPostDecrementLikeDto { public int Id { get; set; } - public int Likes { get; set; } } \ No newline at end of file diff --git a/BlogPlatform/DTO/Post/Request/PatchPostIncrementLikeDto.cs b/BlogPlatform/DTO/Post/Request/PatchPostIncrementLikeDto.cs index d1e85e4..c597ec0 100644 --- a/BlogPlatform/DTO/Post/Request/PatchPostIncrementLikeDto.cs +++ b/BlogPlatform/DTO/Post/Request/PatchPostIncrementLikeDto.cs @@ -3,5 +3,4 @@ namespace BlogPlatform.DTO.Post.Request; public class PatchPostIncrementLikeDto { public int Id { get; set; } - public int Likes { get; set; } } \ No newline at end of file diff --git a/BlogPlatform/Endpoints/Post/CreatePostEndpoint.cs b/BlogPlatform/Endpoints/Post/CreatePostEndpoint.cs new file mode 100644 index 0000000..b64f71c --- /dev/null +++ b/BlogPlatform/Endpoints/Post/CreatePostEndpoint.cs @@ -0,0 +1,41 @@ +using BlogPlatform.DTO.Post.Request; +using BlogPlatform.DTO.Post.Response; +using FastEndpoints; + +namespace BlogPlatform.Endpoints.Post; + +public class CreatePostEndpoint(BlogPlatformDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/posts"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreatePostDto req, CancellationToken ct) + { + var post = new Models.Post() + { + Title = req.Title, + Content = req.Content, + Likes = req.Likes, + CreatedAt = DateOnly.FromDateTime(DateTime.Now), + UserId = req.UserId + }; + + database.Posts.Add(post); + await database.SaveChangesAsync(ct); + + GetPostDto responseDto = new() + { + Id = post.Id, + Title = post.Title, + Content = post.Content, + Likes = post.Likes, + CreatedAt = post.CreatedAt, + UserId = post.UserId + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/BlogPlatform/Endpoints/Post/GetAllPostsEndpoint.cs b/BlogPlatform/Endpoints/Post/GetAllPostsEndpoint.cs new file mode 100644 index 0000000..6f48d54 --- /dev/null +++ b/BlogPlatform/Endpoints/Post/GetAllPostsEndpoint.cs @@ -0,0 +1,6 @@ +namespace BlogPlatform.Endpoints.Post; + +public class GetAllPostsEndpoint +{ + +} \ No newline at end of file diff --git a/BlogPlatform/Endpoints/Post/GetPostEndpoint.cs b/BlogPlatform/Endpoints/Post/GetPostEndpoint.cs new file mode 100644 index 0000000..e514dbb --- /dev/null +++ b/BlogPlatform/Endpoints/Post/GetPostEndpoint.cs @@ -0,0 +1,6 @@ +namespace BlogPlatform.Endpoints.Post; + +public class GetPostEndpoint +{ + +} \ No newline at end of file diff --git a/BlogPlatform/Endpoints/Post/PatchPostDecrementLikeEndpoint.cs b/BlogPlatform/Endpoints/Post/PatchPostDecrementLikeEndpoint.cs new file mode 100644 index 0000000..de65147 --- /dev/null +++ b/BlogPlatform/Endpoints/Post/PatchPostDecrementLikeEndpoint.cs @@ -0,0 +1,53 @@ +using BlogPlatform.DTO.Comment.Response; +using BlogPlatform.DTO.Post.Request; +using BlogPlatform.DTO.Post.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace BlogPlatform.Endpoints.Post; + +public class PatchPostDecrementLikeEndpoint(BlogPlatformDbContext database) : Endpoint +{ + public override void Configure() + { + Patch("/api/posts/{@Id}/DecrementLikes", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchPostDecrementLikeDto req, CancellationToken ct) + { + var post = await database.Posts.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (post == null) + { + await Send.NotFoundAsync(ct); + return; + } + + if (post.Likes > 0) + { + post.Likes = post.Likes--; + } + else post.Likes = 0; + await database.SaveChangesAsync(ct); + + GetPostDto responseDto = new() + { + Id = post.Id, + Title = post.Title, + Content = post.Content, + Likes = post.Likes, + CreatedAt = post.CreatedAt, + UserId = post.UserId, + Comments = post.Comments.Select(c => new GetCommentDto() + { + Id = c.Id, + Content = c.Content, + CreatedAt = c.CreatedAt, + UserId = c.UserId + }).ToList() + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/BlogPlatform/Endpoints/Post/PatchPostIncrementLikeEndpoint.cs b/BlogPlatform/Endpoints/Post/PatchPostIncrementLikeEndpoint.cs new file mode 100644 index 0000000..44079db --- /dev/null +++ b/BlogPlatform/Endpoints/Post/PatchPostIncrementLikeEndpoint.cs @@ -0,0 +1,49 @@ +using BlogPlatform.DTO.Comment.Response; +using BlogPlatform.DTO.Post.Request; +using BlogPlatform.DTO.Post.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace BlogPlatform.Endpoints.Post; + +public class PatchPostIncrementLikeEndpoint(BlogPlatformDbContext database) : Endpoint +{ + public override void Configure() + { + Patch("/api/posts/{@Id}/IncrementLikes", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchPostIncrementLikeDto req, CancellationToken ct) + { + var post = await database.Posts.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (post == null) + { + await Send.NotFoundAsync(ct); + return; + } + + post.Likes = post.Likes++; + await database.SaveChangesAsync(ct); + + GetPostDto responseDto = new() + { + Id = post.Id, + Title = post.Title, + Content = post.Content, + Likes = post.Likes, + CreatedAt = post.CreatedAt, + UserId = post.UserId, + Comments = post.Comments.Select(c => new GetCommentDto() + { + Id = c.Id, + Content = c.Content, + CreatedAt = c.CreatedAt, + UserId = c.UserId + }).ToList() + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/BlogPlatform/Endpoints/Post/UpdatePostEndpoint.cs b/BlogPlatform/Endpoints/Post/UpdatePostEndpoint.cs new file mode 100644 index 0000000..45be386 --- /dev/null +++ b/BlogPlatform/Endpoints/Post/UpdatePostEndpoint.cs @@ -0,0 +1,53 @@ +using BlogPlatform.DTO.Post.Request; +using BlogPlatform.DTO.Post.Response; +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace BlogPlatform.Endpoints.Post; + +public class UpdatePostEndpoint(BlogPlatformDbContext database) : Endpoint +{ + public override void Configure() + { + Put("/api/posts/{@Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(UpdatePostDto req, CancellationToken ct) + { + var post = await database.Posts.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (post == null) + { + await Send.NotFoundAsync(ct); + return; + } + + var checkUser = await database.Users.SingleOrDefaultAsync(x => x.Id == req.UserId, ct); + + if (checkUser == null) + { + await Send.NotFoundAsync(ct); + return; + } + + post.Title = post.Title; + post.Content = post.Content; + post.Likes = post.Likes; + post.CreatedAt = DateOnly.FromDateTime(DateTime.Now); + post.UserId = post.UserId; + await database.SaveChangesAsync(ct); + + GetPostDto responseDto = new() + { + Id = post.Id, + Title = post.Title, + Content = post.Content, + Likes = post.Likes, + CreatedAt = post.CreatedAt, + UserId = post.UserId + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/BlogPlatform/Endpoints/User/UserLoginEndpoint.cs b/BlogPlatform/Endpoints/User/UserLoginEndpoint.cs new file mode 100644 index 0000000..b8ade14 --- /dev/null +++ b/BlogPlatform/Endpoints/User/UserLoginEndpoint.cs @@ -0,0 +1,47 @@ +using BlogPlatform.DTO.User.Request; +using BlogPlatform.DTO.User.Response; +using FastEndpoints; +using FastEndpoints.Security; +using Microsoft.EntityFrameworkCore; + +namespace BlogPlatform.Endpoints.User; + +public class UserLoginEndpoint(BlogPlatformDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/user"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreateUserDto req, CancellationToken ct) + { + var user = await database.Users.SingleOrDefaultAsync(x => x.Username == req.Username, ct); + + if (user == null) + { + await Send.UnauthorizedAsync(ct); + return; + } + + if (BCrypt.Net.BCrypt.Verify(req.Password + user.Salt, user.Password)) + { + var jwtToken = JwtBearer.CreateToken( + o => + { + o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong"; + o.ExpireAt = DateTime.UtcNow.AddMinutes(15); + o.User.Claims.Add(("Username", user.Username)!); + o.User["UserId"] = "001"; + }); + + GetUserDto responseDto = new() + { + Token = jwtToken + }; + + await Send.OkAsync(responseDto, ct); + } + else await Send.UnauthorizedAsync(ct); + } +} \ No newline at end of file