create endpoints from post

This commit is contained in:
2025-10-17 09:56:07 +02:00
parent 2a386ba289
commit 5bf8970d36
11 changed files with 257 additions and 5 deletions

View File

@@ -18,13 +18,12 @@
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.20" />
<PackageReference Include="PasswordGenerator" Version="2.1.0" />
<PackageReference Include="Singulink.Cryptography.PasswordHasher" Version="3.0.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2"/>
</ItemGroup>
<ItemGroup>
<Folder Include="Endpoints\Comment\" />
<Folder Include="Endpoints\Post\" />
<Folder Include="Endpoints\User\" />
</ItemGroup>
</Project>

View File

@@ -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; }
}

View File

@@ -3,5 +3,4 @@ namespace BlogPlatform.DTO.Post.Request;
public class PatchPostDecrementLikeDto
{
public int Id { get; set; }
public int Likes { get; set; }
}

View File

@@ -3,5 +3,4 @@ namespace BlogPlatform.DTO.Post.Request;
public class PatchPostIncrementLikeDto
{
public int Id { get; set; }
public int Likes { get; set; }
}

View File

@@ -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<CreatePostDto, GetPostDto>
{
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);
}
}

View File

@@ -0,0 +1,6 @@
namespace BlogPlatform.Endpoints.Post;
public class GetAllPostsEndpoint
{
}

View File

@@ -0,0 +1,6 @@
namespace BlogPlatform.Endpoints.Post;
public class GetPostEndpoint
{
}

View File

@@ -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<PatchPostDecrementLikeDto, GetPostDto>
{
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);
}
}

View File

@@ -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<PatchPostIncrementLikeDto, GetPostDto>
{
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);
}
}

View File

@@ -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<UpdatePostDto, GetPostDto>
{
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);
}
}

View File

@@ -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<CreateUserDto, GetUserDto>
{
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);
}
}