namespace MyOffice.Web.Controllers; using AutoMapper; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Core; using Core.Extensions; using Models.Account; using Services.Account; using Services.Account.Domain; using Infrastructure.Attributes; using Services.Identity; [Authorize] [ApiController] [Route("api/settings/accounts")] [DefaultFromBody] public class SettingsAccountController : BaseApiController { private readonly ILogger _logger; private readonly IMapper _mapper; private readonly AccountService _accountService; private readonly IContextProvider _contextProvider; public SettingsAccountController( ILogger logger, IMapper mapper, AccountService accountService, IContextProvider contextProvider ) { _logger = logger; _mapper = mapper; _accountService = accountService; _contextProvider = contextProvider; } [HttpGet("invites")] public async Task AccountInvites(CancellationToken cancellationToken) { var invites = await _accountService.InvitesGetAsync(_contextProvider.User.Email, cancellationToken); return OkResponse(_mapper.Map>(invites)); } [HttpPost("invites/{id}/accept")] public async Task AccountInviteAccept([AsGuid] string id, AccountInviteAcceptRequest request, CancellationToken cancellationToken) { var exec = await _accountService.InviteAcceptAsync(UserId, id.AsGuid(), request.Name, cancellationToken); switch (exec.Status) { case InviteAcceptStatus.invite_not_found: return ProblemNotFoundResponse("Invite not found."); case InviteAcceptStatus.account_not_found: return ProblemNotFoundResponse("Account not found."); case InviteAcceptStatus.already_accepted: case InviteAcceptStatus.success: return OkResponse(_mapper.Map(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpPost("invites/{id}/reject")] public async Task AccountInviteReject([AsGuid] string id, CancellationToken cancellationToken) { var exec = await _accountService.InviteRejectAsync(id.AsGuid(), cancellationToken); return MapGeneralExec( exec, result => OkResponse(_mapper.Map(result)), notFoundDetail: "Invite not found.", failureDetail: "Invite reject failed."); } [HttpGet] public async Task AccountsGet([FromQuery][AsGuid(true)] string? category, CancellationToken cancellationToken) { var list = category.IsPresent() ? await _accountService.GetByCategoryAsync(UserId, category!.AsGuid(), cancellationToken) : await _accountService.GetAllAccountsAsync(UserId, cancellationToken); return OkResponse(_mapper.Map>(list.OrderBy(x => x.Name))); } [HttpPost] public async Task AccountsAdd(AccountViewModel request, CancellationToken cancellationToken) { var exec = await _accountService.AccountAddAsync(UserId, new AccountAdd { Name = request.Name, CurrencyId = request.CurrencyId, CategoryId = request.CategoryId.AsGuid(), Type = request.Type, }, cancellationToken); switch (exec.Status) { case AccountAddStatus.category_not_found: return ProblemNotFoundResponse("Category not found."); case AccountAddStatus.currency_not_found: return ProblemNotFoundResponse("Currency not found."); case AccountAddStatus.failure: return ProblemBadResponse("Adding account failed."); case AccountAddStatus.success: return OkResponse(_mapper.Map(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpPut("{id}")] public async Task AccountsUpdate([AsGuid] string id, AccountEditRequestModel request, CancellationToken cancellationToken) { var exec = await _accountService.AccountUpdateAsync(UserId, id.AsGuid(), new AccountEdit { Name = request.Name, CurrencyId = request.CurrencyId, CategoryId = request.CategoryId?.AsGuidNull(), UserId = request.UserId?.AsGuidNull(), Type = request.Type, }, cancellationToken); switch (exec.Status) { case AccountEditStatus.not_found: return ProblemNotFoundResponse("Account not found."); case AccountEditStatus.forbidden: return ProblemForbiddenResponse("Manage access required."); case AccountEditStatus.category_not_found: return ProblemNotFoundResponse("Category not found."); case AccountEditStatus.currency_not_found: return ProblemNotFoundResponse("Currency not found."); case AccountEditStatus.failure: return ProblemBadResponse("Adding account failed."); case AccountEditStatus.success: return OkResponse(_mapper.Map(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpDelete("{id}")] public async Task AccountsDelete([AsGuid] string id, CancellationToken cancellationToken) { var exec = await _accountService.AccountDeleteAsync(UserId, id, cancellationToken); return MapGeneralExec( exec, result => OkResponse(_mapper.Map(result)), notFoundDetail: "Account not found.", forbiddenDetail: "Manage access required."); } [HttpDelete("{id}/category/{categoryId}")] public async Task AccountsCategoryDelete([AsGuid] string id, [AsGuid] string categoryId, CancellationToken cancellationToken) { var exec = await _accountService.AccountCategoryRemoveAsync(UserId, id.AsGuid(), categoryId.AsGuid(), cancellationToken); return MapGeneralExec( exec, result => OkResponse(_mapper.Map(result)), notFoundDetail: "Category not found.", failureDetail: "Category remove failed.", forbiddenDetail: "Manage access required."); } [HttpPost("{id}/access")] public async Task AccountsAccessAdd([AsGuid] string id, AccountAccessViewModel request, CancellationToken cancellationToken) { var model = _mapper.Map>(request.Accesses); var exec = await _accountService.AccessUpdateAsync(UserId, id.AsGuid(), model, cancellationToken); if (exec.Status != GeneralExecStatus.success) { return MapGeneralExec( exec, _ => OkResponse(_mapper.Map(exec.Result!)), notFoundDetail: "Account not found.", failureDetail: "Access update failed.", forbiddenDetail: "Manage access required."); } if (!request.Email.IsPresent()) { return OkResponse(_mapper.Map(exec.Result!)); } var inviteExec = await _accountService.AccessInviteAsync(UserId, id.AsGuid(), request.Email!, request.AllowWrite, cancellationToken); switch (inviteExec.Status) { case AccessInviteStatus.account_not_found: return ProblemNotFoundResponse("Account not found."); case AccessInviteStatus.forbidden: return ProblemForbiddenResponse("Manage access required."); case AccessInviteStatus.access_exists: case AccessInviteStatus.invite_exists: case AccessInviteStatus.success: return OkResponse(_mapper.Map(exec.Result!)); default: throw new NotSupportedException(exec.Status.ToString()); } } [HttpDelete("{id}/access/{userId}")] public async Task AccountsAccessDelete([AsGuid] string id, [AsGuid] string userId, CancellationToken cancellationToken) { var exec = await _accountService.AccessDeleteAsync(UserId, id.AsGuid(), userId.AsGuid(), cancellationToken); return MapGeneralExec( exec, result => OkResponse(_mapper.Map(result)), notFoundDetail: "Account not found.", failureDetail: "Access delete failed.", forbiddenDetail: "Manage access required."); } }