using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; using PrivaPub.ClientModels; using PrivaPub.Extensions; using PrivaPub.Resources; using PrivaPub.Services.ClientToServer.Private; using PrivaPub.ClientModels.User; using PrivaPub.ClientModels.User.Avatar; namespace PrivaPub.Controllers.ClientToServer { [ApiController, Route("clientapi/avatar/private"), Authorize(Policy = Policies.IsUser)] public class PrivateAvatarController : ControllerBase { readonly ILogger _logger; readonly IPrivateAvatarUsersService _privateAvatarUsersService; readonly IStringLocalizer _localizer; public PrivateAvatarController(IPrivateAvatarUsersService privateAvatarUsersService, IStringLocalizer localizer, ILogger logger) { _privateAvatarUsersService = privateAvatarUsersService; _localizer = localizer; _logger = logger; } [HttpGet, Route("/clientapi/avatar/private/list")] public async Task GetAvatars(CancellationToken token) { var result = await _privateAvatarUsersService.GetRootAvatars(User.GetUserId(), token); return result.IsValid ? Ok(result.Data) : StatusCode(result.StatusCode, result); } [HttpPost, Route("/clientapi/avatar/private/insert")] public async Task InsertAvatar(InsertAvatarForm model) { var result = new WebResult(); if (!ModelState.IsValid) return BadRequest(result.Invalidate(_localizer["Invalid model."])); try { model.RootId = User.GetUserId(); result = await _privateAvatarUsersService.InsertAvatar(model); if (!result.IsValid) return StatusCode(result.StatusCode, result); return Ok(result.Data); } catch (Exception ex) { _logger.LogError(ex, $"{nameof(PrivateAvatarController)}.{nameof(InsertAvatar)}()"); return BadRequest(result.Invalidate(_localizer["Something went wrong."])); } } // A login deletes one of its personas, with its password again (R6): everything public it had goes, the groups it owns // with it, as when the whole login is deleted (PersonaRemoval). A suspended persona may be deleted too. [HttpPost, Route("/clientapi/avatar/private/delete"), Microsoft.AspNetCore.RateLimiting.EnableRateLimiting(Infrastructure.RateLimiting.Accounts)] public async Task DeleteAvatar(DeletePersonaForm form, [FromServices] Services.IRootUsersService users, [FromServices] Services.IPersonaRemoval personas, [FromServices] StaticServices.DbEntities dbEntities, CancellationToken token) { if (!ModelState.IsValid) return BadRequest(new WebResult().Invalidate(_localizer["Invalid model."])); var rootId = User.GetUserId(); if (!await users.PasswordMatches(rootId, form.Password)) return StatusCode(StatusCodes.Status403Forbidden, new WebResult().Invalidate(_localizer[Services.RootUsersService.NoMatch], StatusCodes.Status403Forbidden)); if (!await dbEntities.RootToAvatars.Match(ra => ra.RootId == rootId && ra.AvatarId == form.AvatarId).ExecuteAnyAsync(token) || !await personas.Remove(form.AvatarId, CancellationToken.None)) return NotFound(new WebResult().Invalidate(_localizer["Avatar not found."], StatusCodes.Status404NotFound)); return Ok(); } [HttpPost, Route("/clientapi/avatar/private/update")] public async Task UpdateAvatar(UpdateAvatarForm model) { var result = new WebResult(); if (!ModelState.IsValid) return BadRequest(result.Invalidate(_localizer["Invalid model."])); try { model.RootId = User.GetUserId(); result = await _privateAvatarUsersService.UpdateAvatar(model); if (!result.IsValid) return StatusCode(result.StatusCode, result); return Ok(result.Data); } catch (Exception ex) { _logger.LogError(ex, $"{nameof(PrivateAvatarController)}.{nameof(UpdateAvatar)}()"); return BadRequest(result.Invalidate(_localizer["Something went wrong."])); } } } }