2026-10-01 08:05:56 +02:00
using Microsoft.AspNetCore.Authorization ;
using Microsoft.AspNetCore.Mvc ;
using Microsoft.Extensions.Localization ;
using PrivaPub.ClientModels ;
using PrivaPub.ClientModels.Group ;
using PrivaPub.Extensions ;
using PrivaPub.Resources ;
using PrivaPub.Services ;
namespace PrivaPub.Controllers.ClientToServer
{
[ApiController,
Route("clientapi/group"),
Authorize(Policy = Policies.IsUser)]
public class GroupController : ControllerBase
{
readonly IGroupUsersService _groupUsersService ;
readonly IStringLocalizer _localizer ;
public GroupController ( IGroupUsersService groupUsersService , IStringLocalizer < GenericRes > localizer )
{
_groupUsersService = groupUsersService ;
_localizer = localizer ;
}
[HttpGet, Route("/clientapi/group/list")]
public async Task < IActionResult > List ([ FromQuery ] string avatarId , CancellationToken token ) =>
Answer ( await _groupUsersService . GetGroups ( User . GetUserId (), avatarId , token ));
[HttpPost, Route("/clientapi/group/insert")]
public async Task < IActionResult > Insert ( InsertGroupForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . InsertGroup ( User . GetUserId (), form , token ));
[HttpPost, Route("/clientapi/group/update")]
public async Task < IActionResult > Update ( UpdateGroupForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . UpdateGroup ( User . GetUserId (), form , token ));
[HttpPost, Route("/clientapi/group/join")]
public async Task < IActionResult > Join ( JoinGroupForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . JoinGroup ( User . GetUserId (), form , token ));
[HttpPost, Route("/clientapi/group/leave")]
public async Task < IActionResult > Leave ( GroupMembershipForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . LeaveGroup ( User . GetUserId (), form , token ));
[HttpPost, Route("/clientapi/group/approve")]
public async Task < IActionResult > Approve ( GroupMembershipForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . ApproveMember ( User . GetUserId (), form , token ));
2026-10-05 18:24:29 +02:00
[HttpGet, Route("/clientapi/group/members")]
public async Task < IActionResult > Members ([ FromQuery ] string avatarId , [ FromQuery ] string groupId , CancellationToken token ) =>
Answer ( await _groupUsersService . GetMembers ( User . GetUserId (), avatarId , groupId , token ));
[HttpPost, Route("/clientapi/group/reject")]
public async Task < IActionResult > Reject ( GroupMembershipForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . RejectMember ( User . GetUserId (), form , token ));
[HttpPost, Route("/clientapi/group/remove")]
public async Task < IActionResult > Remove ( GroupMembershipForm form , CancellationToken token ) =>
! ModelState . IsValid ? Invalid () : Answer ( await _groupUsersService . RemoveMember ( User . GetUserId (), form , token ));
2026-10-17 05:23:45 +02:00
// the group's owner deletes it, with the login's password (R6): its members and followers are told, its name stays
// taken (GroupRemoval)
[HttpPost, Route("/clientapi/group/delete"), Microsoft.AspNetCore.RateLimiting.EnableRateLimiting(Infrastructure.RateLimiting.Accounts)]
public async Task < IActionResult > Delete ( DeleteGroupForm form , [ FromServices ] IRootUsersService users , [ FromServices ] IGroupRemoval groups ,
[FromServices] StaticServices . DbEntities dbEntities , CancellationToken token )
{
if (! ModelState . IsValid )
return Invalid ();
var rootId = User . GetUserId ();
if (! await users . PasswordMatches ( rootId , form . Password ))
return StatusCode ( StatusCodes . Status403Forbidden , new WebResult (). Invalidate ( _localizer [ RootUsersService . NoMatch ], StatusCodes . Status403Forbidden ));
var owns = await dbEntities . RootToAvatars . Match ( ra => ra . RootId == rootId && ra . AvatarId == form . AvatarId ). ExecuteAnyAsync ( token );
var group = owns ? await dbEntities . Groups . MatchID ( form . GroupId ). Match ( g => ! g . DeletionAt . HasValue ). ExecuteFirstAsync ( token ) : default ;
if ( group == default )
return NotFound ( new WebResult (). Invalidate ( _localizer [ "Group not found." ], StatusCodes . Status404NotFound ));
if ( group . OwnerAvatarId != form . AvatarId )
return StatusCode ( StatusCodes . Status403Forbidden , new WebResult (). Invalidate ( _localizer [ "Only the group's owner can delete it." ], StatusCodes . Status403Forbidden ));
await groups . Remove ( group . ID , CancellationToken . None );
return Ok ();
}
2026-10-01 08:05:56 +02:00
IActionResult Invalid () => BadRequest ( new WebResult (). Invalidate ( _localizer [ "Invalid model." ]));
IActionResult Answer ( WebResult result ) => result . IsValid ? Ok ( result . Data ) : StatusCode ( result . StatusCode , result );
}
}