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 localizer) { _groupUsersService = groupUsersService; _localizer = localizer; } [HttpGet, Route("/clientapi/group/list")] public async Task List([FromQuery] string avatarId, CancellationToken token) => Answer(await _groupUsersService.GetGroups(User.GetUserId(), avatarId, token)); [HttpPost, Route("/clientapi/group/insert")] public async Task Insert(InsertGroupForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.InsertGroup(User.GetUserId(), form, token)); [HttpPost, Route("/clientapi/group/update")] public async Task Update(UpdateGroupForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.UpdateGroup(User.GetUserId(), form, token)); [HttpPost, Route("/clientapi/group/join")] public async Task Join(JoinGroupForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.JoinGroup(User.GetUserId(), form, token)); [HttpPost, Route("/clientapi/group/leave")] public async Task Leave(GroupMembershipForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.LeaveGroup(User.GetUserId(), form, token)); [HttpPost, Route("/clientapi/group/approve")] public async Task Approve(GroupMembershipForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.ApproveMember(User.GetUserId(), form, token)); [HttpGet, Route("/clientapi/group/members")] public async Task 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 Reject(GroupMembershipForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.RejectMember(User.GetUserId(), form, token)); [HttpPost, Route("/clientapi/group/remove")] public async Task Remove(GroupMembershipForm form, CancellationToken token) => !ModelState.IsValid ? Invalid() : Answer(await _groupUsersService.RemoveMember(User.GetUserId(), form, token)); // 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 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(); } IActionResult Invalid() => BadRequest(new WebResult().Invalidate(_localizer["Invalid model."])); IActionResult Answer(WebResult result) => result.IsValid ? Ok(result.Data) : StatusCode(result.StatusCode, result); } }