Created all endpoints to manage groups

This commit is contained in:
2026-02-22 18:39:41 +01:00
parent c67cdf8dd8
commit 9301800d0b
15 changed files with 418 additions and 1 deletions
@@ -0,0 +1,8 @@
namespace BeReadyBackend.DTO.Groups;
public class GetGroupRankingDto
{
public int UserId { get; set; }
public string? Username { get; set; }
public int Score { get; set; }
}
+9
View File
@@ -0,0 +1,9 @@
namespace BeReadyBackend.DTO.Groups;
public class GetProofDto
{
public int UserId { get; set; }
public string? Username { get; set; }
public string? Proof { get; set; }
public int Score { get; set; }
}
@@ -0,0 +1,44 @@
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Services;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
using Group = BeReadyBackend.Models.Group;
namespace BeReadyBackend.Endpoints.Groups;
public class DeleteUserFromGroupRequest
{
public int GroupId { get; set; }
public int UserId { get; set; }
}
public class DeleteUserFromGroupEndpoint(UserGroupsRepository userGroupsRepository, UserService userService) : Endpoint<DeleteUserFromGroupRequest>
{
public override void Configure()
{
Delete("/Groups/{@GroupId}/Users/{@UserId}", x => new { x.GroupId, x.UserId });
}
public override async Task HandleAsync(DeleteUserFromGroupRequest req, CancellationToken ct)
{
int userId = userService.GetUserIdFromToken();
UserGroup? member = await userGroupsRepository.SingleOrDefaultAsync(new GetUserInGroupByIdsSpec(req.GroupId, req.UserId), ct);
if (member is null)
{
await Send.NotFoundAsync(ct);
return;
}
if (member.Grade != "Admin" && userId != req.UserId)
{
await Send.StringAsync("Vous n'avez pas les droits pour supprimer ce membre du groupe", 400, cancellation: ct);
return;
}
await userGroupsRepository.DeleteAsync(member, ct);
await userGroupsRepository.SaveChangesAsync(ct);
await Send.OkAsync(ct);
}
}
@@ -0,0 +1,25 @@
using BeReadyBackend.DTO.Groups;
using BeReadyBackend.Repositories;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
namespace BeReadyBackend.Endpoints.Groups;
public class GroupProofRequest
{
public int Id { get; set; }
}
public class GetAllProofsEndpoint(UserGroupsRepository userGroupsRepository) : Endpoint<GroupProofRequest, List<GetProofDto>>
{
public override void Configure()
{
Get("/Groups/{@Id}/Proofs/", x => new { x.Id });
}
public override async Task HandleAsync(GroupProofRequest req, CancellationToken ct)
{
List<GetProofDto> usersGroup = await userGroupsRepository.ProjectToListAsync<GetProofDto>(new GetUserGroupDetailsByIdSpec(req.Id), ct);
await Send.OkAsync(usersGroup, ct);
}
}
@@ -0,0 +1,54 @@
using BeReadyBackend.DTO.Groups;
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Specifications.Groups;
using BeReadyBackend.Specifications.Users;
using FastEndpoints;
using Group = BeReadyBackend.Models.Group;
namespace BeReadyBackend.Endpoints.Groups;
public class GroupRankingRequest
{
public int Id { get; set; }
}
public class GetGroupRankingEndpoint(
GroupsRepository groupsRepository,
UsersRepository usersRepository,
UserGroupsRepository userGroupsRepository)
: Endpoint<GroupRankingRequest, List<GetGroupRankingDto>>
{
public override void Configure()
{
Get("/Groups/{@Id}/GroupRank", x => new { x.Id });
}
public override async Task HandleAsync(GroupRankingRequest req, CancellationToken ct)
{
Group? group = await groupsRepository.SingleOrDefaultAsync(new GetGroupByIdSpec(req.Id), ct);
if (group is null)
{
await Send.NotFoundAsync(ct);
return;
}
foreach (UserGroup member in group.UserGroups!)
{
if (member.Proof is null) member.Score -= 2;
}
await userGroupsRepository.SaveChangesAsync(ct);
List<GetGroupRankingDto> groupScore = await userGroupsRepository.ProjectToListAsync<GetGroupRankingDto>(new GetGroupRankSpec(req.Id), ct);
int[] points = [5, 3, 1];
for (int i = 0; i < groupScore.Count && i < 3; i++)
{
User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(groupScore[i].UserId), ct);
if (user != null) user.Score += points[i];
}
await usersRepository.SaveChangesAsync(ct);
await Send.OkAsync(groupScore, ct);
}
}
@@ -0,0 +1,34 @@
using BeReadyBackend.Repositories;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
using Group = BeReadyBackend.Models.Group;
namespace BeReadyBackend.Endpoints.Groups;
public class StatusRequest
{
public int GroupId { get; set; }
}
public class PatchGroupStatusEndpoint(GroupsRepository groupsRepository) : Endpoint<StatusRequest>
{
public override void Configure()
{
Patch("/Groups/{@GroupId}/Status/", x => new { x.GroupId });
}
public override async Task HandleAsync(StatusRequest req, CancellationToken ct)
{
Group? group = await groupsRepository.SingleOrDefaultAsync(new GetGroupByIdSpec(req.GroupId), ct);
if (group is null)
{
await Send.NotFoundAsync(ct);
return;
}
group.IsFinished = true;
await groupsRepository.SaveChangesAsync(ct);
await Send.OkAsync(ct);
}
}
@@ -0,0 +1,49 @@
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Services;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
namespace BeReadyBackend.Endpoints.Groups;
public class UserProofRequest
{
public int GroupId { get; set; }
public string? Proof { get; set; }
}
public class PatchGroupUserProofEndpoint(UserGroupsRepository userGroupsRepository, UserService userService) : Endpoint<UserProofRequest>
{
public override void Configure()
{
Patch("/Groups/{@GroupId}/Users/Proof/", x => new { x.GroupId });
}
public override async Task HandleAsync(UserProofRequest req, CancellationToken ct)
{
int userId = userService.GetUserIdFromToken();
UserGroup? member = await userGroupsRepository.SingleOrDefaultAsync(new GetUserInGroupByIdsSpec(req.GroupId, userId), ct);
if (member is null)
{
await Send.NotFoundAsync(ct);
return;
}
if (member.Proof is not null)
{
await Send.StringAsync("Vous avez déjà déposé une photo", 400, cancellation: ct);
return;
}
if (member.Group!.IsFinished)
{
await Send.StringAsync("Ce défi est terminé", 400, cancellation: ct);
return;
}
member.Proof = req.Proof;
await userGroupsRepository.SaveChangesAsync(ct);
await Send.OkAsync(ct);
}
}
@@ -0,0 +1,43 @@
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Services;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
namespace BeReadyBackend.Endpoints.Groups;
public class UserRoleRequest
{
public int GroupId { get; set; }
public int UserId { get; set; }
}
public class PatchGroupUserRoleEndpoint(UserGroupsRepository userGroupsRepository, UserService userService) : Endpoint<UserRoleRequest>
{
public override void Configure()
{
Patch("/Groups/{@GroupId}/Users/{@UserId}/Role/", x => new { x.GroupId, x.UserId });
}
public override async Task HandleAsync(UserRoleRequest req, CancellationToken ct)
{
int userId = userService.GetUserIdFromToken();
UserGroup? member = await userGroupsRepository.SingleOrDefaultAsync(new GetUserInGroupByIdsSpec(req.GroupId, req.UserId), ct);
if (member is null)
{
await Send.NotFoundAsync(ct);
return;
}
if (member.Grade != "Admin" && userId != req.UserId)
{
await Send.StringAsync("Vous n'avez pas les droits pour changer le rôle de ce membre", 400, cancellation: ct);
return;
}
member.Grade = "Admin";
await userGroupsRepository.SaveChangesAsync(ct);
await Send.OkAsync(ct);
}
}
@@ -0,0 +1,49 @@
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Services;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
namespace BeReadyBackend.Endpoints.Groups;
public class UserVoteRequest
{
public int GroupId { get; set; }
public int VotedProofId { get; set; }
}
public class PatchVoteEndpoint(UserGroupsRepository userGroupsRepository, UserService userService) : Endpoint<UserVoteRequest>
{
public override void Configure()
{
Patch("/Groups/{@GroupId}/Users/Vote/", x => new { x.GroupId });
}
public override async Task HandleAsync(UserVoteRequest req, CancellationToken ct)
{
int userId = userService.GetUserIdFromToken();
UserGroup? member = await userGroupsRepository.SingleOrDefaultAsync(new GetUserInGroupByIdsSpec(req.GroupId, userId), ct);
if (member is null)
{
await Send.NotFoundAsync(ct);
return;
}
if (member.VotedProofId is not null)
{
await Send.StringAsync("Vous ne pouvez pas voter plusieurs fois", 400, cancellation: ct);
return;
}
if (member.Group!.IsFinished)
{
await Send.StringAsync("Ce défi est terminé", 400, cancellation: ct);
return;
}
member.VotedProofId = req.VotedProofId;
await userGroupsRepository.SaveChangesAsync(ct);
await Send.OkAsync(ct);
}
}
@@ -0,0 +1,55 @@
using BeReadyBackend.Models;
using BeReadyBackend.Repositories;
using BeReadyBackend.Services;
using BeReadyBackend.Specifications.Groups;
using FastEndpoints;
using Group = BeReadyBackend.Models.Group;
namespace BeReadyBackend.Endpoints.Groups;
public class GroupVoteRequest
{
public int Id { get; set; }
}
public class StartVoteEndpoint(UserGroupsRepository userGroupsRepository, GroupsRepository groupsRepository, UserService userService) : Endpoint<GroupVoteRequest>
{
public override void Configure()
{
Post("/Groups/{@Id}/Vote/", x => new { x.Id });
}
public override async Task HandleAsync(GroupVoteRequest req, CancellationToken ct)
{
Group? group = await groupsRepository.SingleOrDefaultAsync(new GetGroupByIdSpec(req.Id), ct);
if (group is null)
{
await Send.NotFoundAsync(ct);
return;
}
UserGroup? userGroup = group.UserGroups!.FirstOrDefault(x => x.UserId == userService.GetUserIdFromToken());
if (userGroup?.Grade != "Admin")
{
await Send.StringAsync("Vous ne pouvez pas lancer le vote", 400, cancellation: ct);
return;
}
if (group.IsFinished)
{
await Send.StringAsync("Le défi est terminé", 400, cancellation: ct);
return;
}
if (group.CreationDate.AddHours(group.Duration) > DateTime.Now)
{
await Send.StringAsync("Le défi n'est pas terminé", 400, cancellation: ct);
return;
}
await Send.OkAsync(ct);
}
}
@@ -17,6 +17,6 @@ public class DtoToEntityMappings : Profile
CreateMap<PatchUserDesignationDto, User>();
CreateMap<CreateGroupDto, Group>()
.ForMember(dest => dest.UserGroups, opt => opt.Ignore());;
.ForMember(dest => dest.UserGroups, opt => opt.Ignore());
}
}
@@ -64,5 +64,11 @@ public class EntityToDtoMappings : Profile
CreateMap<Message, GetMessageDto>()
.ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.User!.Username));
CreateMap<UserGroup, GetProofDto>()
.ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.User!.Username));
CreateMap<UserGroup, GetGroupRankingDto>()
.ForMember(dest => dest.Username, opt => opt.MapFrom(src => src.User!.Username));
}
}
@@ -0,0 +1,14 @@
using Ardalis.Specification;
using BeReadyBackend.Models;
namespace BeReadyBackend.Specifications.Groups;
public class GetGroupRankSpec : Specification<UserGroup>
{
public GetGroupRankSpec(int id)
{
Query
.Where(x => x.GroupId == id)
.OrderByDescending(x => x.Score);
}
}
@@ -0,0 +1,13 @@
using Ardalis.Specification;
using BeReadyBackend.Models;
namespace BeReadyBackend.Specifications.Groups;
public class GetUserGroupDetailsByIdSpec : Specification<UserGroup>
{
public GetUserGroupDetailsByIdSpec(int groupId)
{
Query
.Where(x => x.GroupId == groupId);
}
}
@@ -0,0 +1,14 @@
using Ardalis.Specification;
using BeReadyBackend.Models;
namespace BeReadyBackend.Specifications.Groups;
public class GetUserInGroupByIdsSpec : SingleResultSpecification<UserGroup>
{
public GetUserInGroupByIdsSpec(int groupId, int userId)
{
Query
.Include(x => x.Group)
.Where(x => x.GroupId == groupId && x.UserId == userId);
}
}