add account management
This commit is contained in:
parent
2d7d23d26b
commit
7229a10ad5
@ -1,10 +1,13 @@
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.AddAccount;
|
||||
namespace cuqmbr.TravelGuide.Application.Identity
|
||||
.Accounts.Commands.AddAccount;
|
||||
|
||||
public record AddAccountCommand : IRequest<AccountDto>
|
||||
{
|
||||
public string Username { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
@ -3,7 +3,8 @@ using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.AddAccount;
|
||||
namespace cuqmbr.TravelGuide.Application
|
||||
.Identity.Accounts.Commands.AddAccount;
|
||||
|
||||
public class AddAccountCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<AddAccountCommand>
|
||||
|
@ -7,34 +7,33 @@ using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.AddAccount;
|
||||
namespace cuqmbr.TravelGuide.Application
|
||||
.Identity.Accounts.Commands.AddAccount;
|
||||
|
||||
public class AddAccountCommandHandler :
|
||||
IRequestHandler<AddAccountCommand, AccountDto>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly PasswordHasherService _passwordHasherService;
|
||||
private readonly PasswordHasherService _passwordHasher;
|
||||
|
||||
public AddAccountCommandHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper,
|
||||
PasswordHasherService passwordHasherService)
|
||||
public AddAccountCommandHandler(UnitOfWork unitOfWork,
|
||||
IMapper mapper, PasswordHasherService passwordHasher)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
_passwordHasherService = passwordHasherService;
|
||||
_passwordHasher = passwordHasher;
|
||||
}
|
||||
|
||||
public async Task<AccountDto> Handle(
|
||||
AddAccountCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var user = await _unitOfWork.AccountRepository.GetOneAsync(
|
||||
var account = await _unitOfWork.AccountRepository.GetOneAsync(
|
||||
e => e.Email == request.Email,
|
||||
cancellationToken);
|
||||
|
||||
if (user != null)
|
||||
if (account != null)
|
||||
{
|
||||
throw new DuplicateEntityException();
|
||||
}
|
||||
@ -47,15 +46,16 @@ public class AddAccountCommandHandler :
|
||||
.Items;
|
||||
|
||||
var salt = RandomNumberGenerator.GetBytes(128 / 8);
|
||||
var hash = await _passwordHasherService.HashAsync(
|
||||
var hash = await _passwordHasher.HashAsync(
|
||||
Encoding.UTF8.GetBytes(request.Password),
|
||||
salt, cancellationToken);
|
||||
|
||||
var saltBase64 = Convert.ToBase64String(salt);
|
||||
var hashBase64 = Convert.ToBase64String(hash);
|
||||
|
||||
user = new Account()
|
||||
account = new Account()
|
||||
{
|
||||
Username = request.Username,
|
||||
Email = request.Email,
|
||||
PasswordHash = hashBase64,
|
||||
PasswordSalt = saltBase64,
|
||||
@ -66,12 +66,12 @@ public class AddAccountCommandHandler :
|
||||
.ToArray()
|
||||
};
|
||||
|
||||
user = await _unitOfWork.AccountRepository.AddOneAsync(
|
||||
user, cancellationToken);
|
||||
account = await _unitOfWork.AccountRepository.AddOneAsync(
|
||||
account, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return _mapper.Map<AccountDto>(user);
|
||||
return _mapper.Map<AccountDto>(account);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,37 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.AddAccount;
|
||||
namespace cuqmbr.TravelGuide.Application
|
||||
.Identity.Accounts.Commands.AddAccount;
|
||||
|
||||
public class AddAccountCommandValidator : AbstractValidator<AddAccountCommand>
|
||||
public class AddAccountCommandValidator :
|
||||
AbstractValidator<AddAccountCommand>
|
||||
{
|
||||
public AddAccountCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Username)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
.MinimumLength(1)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MinimumLength"],
|
||||
1))
|
||||
.MaximumLength(32)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
32))
|
||||
.IsUsername()
|
||||
.WithMessage(localizer["FluentValidation.IsUsername"]);
|
||||
|
||||
RuleFor(v => v.Email)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"])
|
||||
@ -32,5 +53,18 @@ public class AddAccountCommandValidator : AbstractValidator<AddAccountCommand>
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
|
||||
RuleFor(v => v.Roles ?? new IdentityRole[0])
|
||||
.IsUnique(r => r)
|
||||
.WithMessage(localizer["FluentValidation.IsUnique"]);
|
||||
|
||||
RuleForEach(v => v.Roles)
|
||||
.Must(r => IdentityRole.Enumerations.ContainsValue(r))
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
localizer["FluentValidation.MustBeInEnum"],
|
||||
String.Join(
|
||||
", ",
|
||||
IdentityRole.Enumerations.Values.Select(e => e.Name))));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,9 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity
|
||||
.Accounts.Commands.DeleteAccount;
|
||||
|
||||
public record DeleteAccountCommand : IRequest
|
||||
{
|
||||
public Guid Guid { get; set; }
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity
|
||||
.Accounts.Commands.DeleteAccount;
|
||||
|
||||
public class DeleteAccountCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<DeleteAccountCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public DeleteAccountCommandAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(DeleteAccountCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.DeleteAccount;
|
||||
|
||||
public class DeleteAccountCommandHandler : IRequestHandler<DeleteAccountCommand>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
|
||||
public DeleteAccountCommandHandler(UnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task Handle(
|
||||
DeleteAccountCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var account = await _unitOfWork.AccountRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, cancellationToken);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await _unitOfWork.AccountRepository.DeleteOneAsync(
|
||||
account, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.DeleteAccount;
|
||||
|
||||
public class DeleteAccountCommandValidator : AbstractValidator<DeleteAccountCommand>
|
||||
{
|
||||
public DeleteAccountCommandValidator(IStringLocalizer localizer)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application
|
||||
.Identity.Accounts.Commands.UpdateAccount;
|
||||
|
||||
public record UpdateAccountCommand : IRequest<AccountDto>
|
||||
{
|
||||
public Guid Guid { get; set; }
|
||||
|
||||
public string? Username { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
public string? Password { get; set; }
|
||||
|
||||
public ICollection<IdentityRole>? Roles { get; set; }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.UpdateAccount;
|
||||
|
||||
public class UpdateAccountCommandAuthorizer :
|
||||
AbstractRequestAuthorizer<UpdateAccountCommand>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public UpdateAccountCommandAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(UpdateAccountCommand request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application
|
||||
.Identity.Accounts.Commands.UpdateAccount;
|
||||
|
||||
public class UpdateAccountCommandHandler :
|
||||
IRequestHandler<UpdateAccountCommand, AccountDto>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly PasswordHasherService _passwordHasher;
|
||||
|
||||
public UpdateAccountCommandHandler(UnitOfWork unitOfWork,
|
||||
IMapper mapper, PasswordHasherService passwordHasher)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
_passwordHasher = passwordHasher;
|
||||
}
|
||||
|
||||
public async Task<AccountDto> Handle(
|
||||
UpdateAccountCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var account = await _unitOfWork.AccountRepository
|
||||
.GetOneAsync(e => e.Guid == request.Guid,
|
||||
e => e.AccountRoles, cancellationToken);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
|
||||
account.Username = request.Username ?? account.Username;
|
||||
account.Email = request.Email ?? account.Email;
|
||||
|
||||
if (request.Password != null)
|
||||
{
|
||||
var salt = RandomNumberGenerator.GetBytes(128 / 8);
|
||||
var hash = await _passwordHasher.HashAsync(
|
||||
Encoding.UTF8.GetBytes(request.Password),
|
||||
salt, cancellationToken);
|
||||
|
||||
var saltBase64 = Convert.ToBase64String(salt);
|
||||
var hashBase64 = Convert.ToBase64String(hash);
|
||||
|
||||
account.PasswordHash = hashBase64;
|
||||
account.PasswordSalt = saltBase64;
|
||||
}
|
||||
|
||||
|
||||
if (request.Roles != null)
|
||||
{
|
||||
var requestRoleIds = (await _unitOfWork.RoleRepository
|
||||
.GetPageAsync(
|
||||
r => request.Roles.Contains(r.Value),
|
||||
1, request.Roles.Count, cancellationToken))
|
||||
.Items
|
||||
.Select(r => r.Id);
|
||||
|
||||
var accountRoles = account.AccountRoles;
|
||||
var accountRoleIds = accountRoles.Select(ar => ar.RoleId);
|
||||
|
||||
var commonRoleIds = requestRoleIds.Intersect(accountRoleIds);
|
||||
|
||||
var newRoleIds = requestRoleIds.Except(accountRoleIds);
|
||||
|
||||
var combinedRoleIds = commonRoleIds.Union(newRoleIds);
|
||||
|
||||
account.AccountRoles = combinedRoleIds.Select(rId =>
|
||||
new AccountRole()
|
||||
{
|
||||
Id = accountRoles.FirstOrDefault(ar =>
|
||||
ar.RoleId == rId)?.Id ?? default,
|
||||
RoleId = rId
|
||||
})
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
var accountRoleIds = account.AccountRoles.Select(ar => ar.RoleId);
|
||||
var accountRoles = (await _unitOfWork.AccountRoleRepository
|
||||
.GetPageAsync(
|
||||
ar => accountRoleIds.Contains(ar.RoleId),
|
||||
ar => ar.Role,
|
||||
1, accountRoleIds.Count(), cancellationToken))
|
||||
.Items;
|
||||
|
||||
account.AccountRoles = accountRoles.ToList();
|
||||
}
|
||||
|
||||
|
||||
account = await _unitOfWork.AccountRepository.UpdateOneAsync(
|
||||
account, cancellationToken);
|
||||
|
||||
await _unitOfWork.SaveAsync(cancellationToken);
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return _mapper.Map<AccountDto>(account);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.FluentValidation;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application
|
||||
.Identity.Accounts.Commands.UpdateAccount;
|
||||
|
||||
public class UpdateAccountCommandValidator :
|
||||
AbstractValidator<UpdateAccountCommand>
|
||||
{
|
||||
public UpdateAccountCommandValidator(
|
||||
IStringLocalizer localizer,
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
|
||||
RuleFor(v => v.Username)
|
||||
.MinimumLength(1)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MinimumLength"],
|
||||
1))
|
||||
.MaximumLength(32)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
32))
|
||||
.IsUsername()
|
||||
.WithMessage(localizer["FluentValidation.IsUsername"]);
|
||||
|
||||
RuleFor(v => v.Email)
|
||||
.IsEmail()
|
||||
.WithMessage(localizer["FluentValidation.IsEmail"]);
|
||||
|
||||
RuleFor(v => v.Password)
|
||||
.MinimumLength(8)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MinimumLength"],
|
||||
8))
|
||||
.MaximumLength(64)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
|
||||
RuleFor(v => v.Roles ?? new IdentityRole[0])
|
||||
.IsUnique(r => r)
|
||||
.WithMessage(localizer["FluentValidation.IsUnique"]);
|
||||
|
||||
RuleForEach(v => v.Roles)
|
||||
.Must(r => IdentityRole.Enumerations.ContainsValue(r))
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
localizer["FluentValidation.MustBeInEnum"],
|
||||
String.Join(
|
||||
", ",
|
||||
IdentityRole.Enumerations.Values.Select(e => e.Name))));
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccount;
|
||||
|
||||
public record GetAccountQuery : IRequest<AccountDto>
|
||||
{
|
||||
public Guid Guid { get; set; }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccount;
|
||||
|
||||
public class GetAccountQueryAuthorizer :
|
||||
AbstractRequestAuthorizer<GetAccountQuery>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public GetAccountQueryAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(GetAccountQuery request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using cuqmbr.TravelGuide.Application.Common.Exceptions;
|
||||
using AutoMapper;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccount;
|
||||
|
||||
public class GetAccountQueryHandler :
|
||||
IRequestHandler<GetAccountQuery, AccountDto>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetAccountQueryHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<AccountDto> Handle(
|
||||
GetAccountQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var account = await _unitOfWork.AccountRepository.GetOneAsync(
|
||||
e => e.Guid == request.Guid, e => e.AccountRoles,
|
||||
cancellationToken);
|
||||
|
||||
if (account == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
|
||||
var accountRoleIds = account.AccountRoles.Select(ar => ar.RoleId);
|
||||
var accountRoles = (await _unitOfWork.AccountRoleRepository
|
||||
.GetPageAsync(
|
||||
ar => accountRoleIds.Contains(ar.RoleId),
|
||||
ar => ar.Role,
|
||||
1, accountRoleIds.Count(), cancellationToken))
|
||||
.Items;
|
||||
|
||||
account.AccountRoles = accountRoles.ToList();
|
||||
|
||||
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return _mapper.Map<AccountDto>(account);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccount;
|
||||
|
||||
public class GetAccountQueryValidator : AbstractValidator<GetAccountQuery>
|
||||
{
|
||||
public GetAccountQueryValidator(IStringLocalizer localizer)
|
||||
{
|
||||
RuleFor(v => v.Guid)
|
||||
.NotEmpty()
|
||||
.WithMessage(localizer["FluentValidation.NotEmpty"]);
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccountsPage;
|
||||
|
||||
public record GetAccountsPageQuery : IRequest<PaginatedList<AccountDto>>
|
||||
{
|
||||
public int PageNumber { get; set; } = 1;
|
||||
|
||||
public int PageSize { get; set; } = 10;
|
||||
|
||||
public string Search { get; set; } = String.Empty;
|
||||
|
||||
public string Sort { get; set; } = String.Empty;
|
||||
|
||||
public ICollection<IdentityRole>? Roles { get; set; }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Authorization;
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using cuqmbr.TravelGuide.Domain.Enums;
|
||||
using MediatR.Behaviors.Authorization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccountsPage;
|
||||
|
||||
public class GetAccountsPageQueryAuthorizer :
|
||||
AbstractRequestAuthorizer<GetAccountsPageQuery>
|
||||
{
|
||||
private readonly SessionUserService _sessionUserService;
|
||||
|
||||
public GetAccountsPageQueryAuthorizer(SessionUserService sessionUserService)
|
||||
{
|
||||
_sessionUserService = sessionUserService;
|
||||
}
|
||||
|
||||
public override void BuildPolicy(GetAccountsPageQuery request)
|
||||
{
|
||||
UseRequirement(new MustBeAuthenticatedRequirement
|
||||
{
|
||||
IsAuthenticated= _sessionUserService.IsAuthenticated
|
||||
});
|
||||
|
||||
UseRequirement(new MustBeInRolesRequirement
|
||||
{
|
||||
RequiredRoles = [IdentityRole.Administrator],
|
||||
UserRoles = _sessionUserService.Roles
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
using MediatR;
|
||||
using cuqmbr.TravelGuide.Application.Common.Persistence;
|
||||
using AutoMapper;
|
||||
using cuqmbr.TravelGuide.Application.Common.Models;
|
||||
using cuqmbr.TravelGuide.Application.Common.Extensions;
|
||||
using cuqmbr.TravelGuide.Domain.Entities;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccountsPage;
|
||||
|
||||
public class GetAccountsPageQueryHandler :
|
||||
IRequestHandler<GetAccountsPageQuery, PaginatedList<AccountDto>>
|
||||
{
|
||||
private readonly UnitOfWork _unitOfWork;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public GetAccountsPageQueryHandler(
|
||||
UnitOfWork unitOfWork,
|
||||
IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<PaginatedList<AccountDto>> Handle(
|
||||
GetAccountsPageQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var paginatedList = await _unitOfWork.AccountRepository.GetPageAsync(
|
||||
a =>
|
||||
(a.Username.ToLower().Contains(request.Search.ToLower()) ||
|
||||
a.Email.ToLower().Contains(request.Search.ToLower())) &&
|
||||
(request.Roles != null
|
||||
? request.Roles.All(r => a.AccountRoles.Any(ar => ar.Role.Value == r))
|
||||
: true),
|
||||
a => a.AccountRoles,
|
||||
request.PageNumber, request.PageSize, cancellationToken);
|
||||
|
||||
|
||||
var accounts = paginatedList.Items;
|
||||
|
||||
var accountsRoleIds = accounts
|
||||
.SelectMany(a => a.AccountRoles)
|
||||
.Select(ar => ar.RoleId)
|
||||
.Distinct();
|
||||
|
||||
var roles = (await _unitOfWork.RoleRepository
|
||||
.GetPageAsync(
|
||||
r => accountsRoleIds.Contains(r.Id),
|
||||
1, accountsRoleIds.Count(), cancellationToken))
|
||||
.Items;
|
||||
|
||||
foreach (var account in accounts)
|
||||
{
|
||||
account.AccountRoles = account.AccountRoles.Select(ar =>
|
||||
new AccountRole()
|
||||
{
|
||||
RoleId = ar.RoleId,
|
||||
Role = roles.Single(r => r.Id == ar.RoleId),
|
||||
AccountId = account.Id,
|
||||
Account = account
|
||||
})
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
|
||||
var mappedItems = _mapper
|
||||
.ProjectTo<AccountDto>(accounts.AsQueryable());
|
||||
|
||||
mappedItems = QueryableExtension<AccountDto>
|
||||
.ApplySort(mappedItems, request.Sort);
|
||||
|
||||
_unitOfWork.Dispose();
|
||||
|
||||
return new PaginatedList<AccountDto>(
|
||||
mappedItems.ToList(),
|
||||
paginatedList.TotalCount, request.PageNumber,
|
||||
request.PageSize);
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
using cuqmbr.TravelGuide.Application.Common.Services;
|
||||
using FluentValidation;
|
||||
using Microsoft.Extensions.Localization;
|
||||
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccountsPage;
|
||||
|
||||
public class GetAccountsPageQueryValidator : AbstractValidator<GetAccountsPageQuery>
|
||||
{
|
||||
public GetAccountsPageQueryValidator(
|
||||
IStringLocalizer localizer,
|
||||
SessionCultureService cultureService)
|
||||
{
|
||||
RuleFor(v => v.PageNumber)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.GreaterThanOrEqualTo"],
|
||||
1));
|
||||
|
||||
RuleFor(v => v.PageSize)
|
||||
.GreaterThanOrEqualTo(1)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.GreaterThanOrEqualTo"],
|
||||
1))
|
||||
.LessThanOrEqualTo(50)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.LessThanOrEqualTo"],
|
||||
50));
|
||||
|
||||
RuleFor(v => v.Search)
|
||||
.MaximumLength(64)
|
||||
.WithMessage(
|
||||
String.Format(
|
||||
cultureService.Culture,
|
||||
localizer["FluentValidation.MaximumLength"],
|
||||
64));
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ namespace cuqmbr.TravelGuide.Application.Identity.Accounts.ViewModels;
|
||||
|
||||
public sealed class AddAccountViewModel
|
||||
{
|
||||
public string Username { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
|
||||
public string Password { get; set; }
|
||||
|
@ -0,0 +1,6 @@
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.ViewModels;
|
||||
|
||||
public sealed class GetAccountsPageFilterViewModel
|
||||
{
|
||||
public ICollection<string>? Roles { get; set; }
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
namespace cuqmbr.TravelGuide.Application.Identity.Accounts.ViewModels;
|
||||
|
||||
public sealed class UpdateAccountViewModel
|
||||
{
|
||||
public Guid Uuid { get; set; }
|
||||
|
||||
public string? Username { get; set; }
|
||||
|
||||
public string? Email { get; set; }
|
||||
|
||||
public string? Password { get; set; }
|
||||
|
||||
public ICollection<string>? Roles { get; set; }
|
||||
}
|
@ -7,12 +7,10 @@ using cuqmbr.TravelGuide.Application.Identity.Roles.Queries.GetRolesPage;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts.ViewModels;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.AddAccount;
|
||||
// using cuqmbr.TravelGuide.Application.Identity.Commands.AddIdentity;
|
||||
// using cuqmbr.TravelGuide.Application.Identity.Queries.GetIdentityPage;
|
||||
// using cuqmbr.TravelGuide.Application.Identity.Queries.GetIdentity;
|
||||
// using cuqmbr.TravelGuide.Application.Identity.Commands.UpdateIdentity;
|
||||
// using cuqmbr.TravelGuide.Application.Identity.Commands.DeleteIdentity;
|
||||
// using cuqmbr.TravelGuide.Application.Identity.ViewModels;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccountsPage;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts.Queries.GetAccount;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.UpdateAccount;
|
||||
using cuqmbr.TravelGuide.Application.Identity.Accounts.Commands.DeleteAccount;
|
||||
|
||||
namespace cuqmbr.TravelGuide.HttpApi.Controllers;
|
||||
|
||||
@ -78,7 +76,7 @@ public class IdentityController : ControllerBase
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
typeof(ProblemDetails))]
|
||||
public async Task<ActionResult<AccountDto>> Add(
|
||||
public async Task<ActionResult<AccountDto>> AddAccount(
|
||||
[FromBody] AddAccountViewModel viewModel,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@ -87,6 +85,7 @@ public class IdentityController : ControllerBase
|
||||
await Mediator.Send(
|
||||
new AddAccountCommand()
|
||||
{
|
||||
Username = viewModel.Username,
|
||||
Email = viewModel.Email,
|
||||
Password = viewModel.Password,
|
||||
Roles = viewModel.Roles
|
||||
@ -96,147 +95,144 @@ public class IdentityController : ControllerBase
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("accounts")]
|
||||
[SwaggerOperation("Get a list of all accounts")]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status200OK, "Request successful",
|
||||
typeof(PaginatedList<AccountDto>))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
typeof(HttpValidationProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status403Forbidden,
|
||||
"Not enough privileges to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
typeof(ProblemDetails))]
|
||||
public async Task<PaginatedList<AccountDto>> GetAccountsPage(
|
||||
[FromQuery] PageQuery pageQuery, [FromQuery] SearchQuery searchQuery,
|
||||
[FromQuery] SortQuery sortQuery,
|
||||
[FromQuery] GetAccountsPageFilterViewModel filterQuery,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await Mediator.Send(
|
||||
new GetAccountsPageQuery()
|
||||
{
|
||||
PageNumber = pageQuery.PageNumber,
|
||||
PageSize = pageQuery.PageSize,
|
||||
Search = searchQuery.Search,
|
||||
Sort = sortQuery.Sort,
|
||||
Roles = filterQuery.Roles == null ? null :
|
||||
filterQuery.Roles
|
||||
.Select(s => IdentityRole.FromName(s))
|
||||
.ToArray()
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet("accounts/{uuid:guid}")]
|
||||
[SwaggerOperation("Get an account by uuid")]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status200OK, "Request successful", typeof(AccountDto))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
typeof(HttpValidationProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status403Forbidden,
|
||||
"Not enough privileges to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status404NotFound, "Object not found", typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
typeof(ProblemDetails))]
|
||||
public async Task<AccountDto> GetAccount(
|
||||
[FromRoute] Guid uuid,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await Mediator.Send(new GetAccountQuery() { Guid = uuid },
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPut("accounts/{uuid:guid}")]
|
||||
[SwaggerOperation("Update an account")]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status200OK, "Request successful", typeof(AccountDto))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status400BadRequest, "Object already exists",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
typeof(HttpValidationProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status403Forbidden,
|
||||
"Not enough privileges to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status404NotFound, "Object not found",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status404NotFound, "Parent object not found",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
typeof(ProblemDetails))]
|
||||
public async Task<AccountDto> UpdateAccount(
|
||||
[FromRoute] Guid uuid,
|
||||
[FromBody] UpdateAccountViewModel viewModel,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return await Mediator.Send(
|
||||
new UpdateAccountCommand()
|
||||
{
|
||||
Guid = uuid,
|
||||
Username = viewModel.Username,
|
||||
Email = viewModel.Email,
|
||||
Password = viewModel.Password,
|
||||
Roles = viewModel.Roles == null ? null :
|
||||
viewModel.Roles
|
||||
.Select(s => IdentityRole.FromName(s))
|
||||
.ToArray()
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
// [HttpPost]
|
||||
// [SwaggerOperation("Add an identity")]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status201Created, "Object successfuly created",
|
||||
// typeof(IdentityDto))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status400BadRequest, "Object already exists",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
// typeof(HttpValidationProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status403Forbidden,
|
||||
// "Not enough privileges to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status404NotFound, "Parent object not found",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
// typeof(ProblemDetails))]
|
||||
// public async Task<ActionResult<IdentityDto>> Add(
|
||||
// [FromBody] AddIdentityViewModel viewModel,
|
||||
// CancellationToken cancellationToken)
|
||||
// {
|
||||
// return StatusCode(
|
||||
// StatusCodes.Status201Created,
|
||||
// await Mediator.Send(
|
||||
// new AddIdentityCommand()
|
||||
// {
|
||||
// Name = viewModel.Name,
|
||||
// Longitude = viewModel.Longitude,
|
||||
// Latitude = viewModel.Latitude,
|
||||
// VehicleType = VehicleType.FromName(viewModel.VehicleType),
|
||||
// CityGuid = viewModel.CityUuid
|
||||
// },
|
||||
// cancellationToken));
|
||||
// }
|
||||
//
|
||||
// [HttpGet("{uuid:guid}")]
|
||||
// [SwaggerOperation("Get an identity by uuid")]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status200OK, "Request successful", typeof(IdentityDto))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
// typeof(HttpValidationProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status403Forbidden,
|
||||
// "Not enough privileges to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status404NotFound, "Object not found", typeof(IdentityDto))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
// typeof(ProblemDetails))]
|
||||
// public async Task<IdentityDto> Get(
|
||||
// [FromRoute] Guid uuid,
|
||||
// CancellationToken cancellationToken)
|
||||
// {
|
||||
// return await Mediator.Send(new GetIdentityQuery() { Guid = uuid },
|
||||
// cancellationToken);
|
||||
// }
|
||||
//
|
||||
// [HttpPut("{uuid:guid}")]
|
||||
// [SwaggerOperation("Update an identity")]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status200OK, "Request successful", typeof(IdentityDto))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status400BadRequest, "Object already exists",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
// typeof(HttpValidationProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status403Forbidden,
|
||||
// "Not enough privileges to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status404NotFound, "Object not found", typeof(IdentityDto))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status404NotFound, "Parent object not found",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
// typeof(ProblemDetails))]
|
||||
// public async Task<IdentityDto> Update(
|
||||
// [FromRoute] Guid uuid,
|
||||
// [FromBody] UpdateIdentityViewModel viewModel,
|
||||
// CancellationToken cancellationToken)
|
||||
// {
|
||||
// return await Mediator.Send(
|
||||
// new UpdateIdentityCommand()
|
||||
// {
|
||||
// Guid = uuid,
|
||||
// Name = viewModel.Name,
|
||||
// Longitude = viewModel.Longitude,
|
||||
// Latitude = viewModel.Latitude,
|
||||
// VehicleType = VehicleType.FromName(viewModel.VehicleType),
|
||||
// CityGuid = viewModel.CityUuid
|
||||
// },
|
||||
// cancellationToken);
|
||||
// }
|
||||
//
|
||||
// [HttpDelete("{uuid:guid}")]
|
||||
// [SwaggerOperation("Delete an identity")]
|
||||
// [SwaggerResponse(StatusCodes.Status204NoContent, "Request successful")]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
// typeof(HttpValidationProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status403Forbidden,
|
||||
// "Not enough privileges to perform an action",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status404NotFound, "Object not found",
|
||||
// typeof(ProblemDetails))]
|
||||
// [SwaggerResponse(
|
||||
// StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
// typeof(ProblemDetails))]
|
||||
// public async Task<IActionResult> Delete(
|
||||
// [FromRoute] Guid uuid,
|
||||
// CancellationToken cancellationToken)
|
||||
// {
|
||||
// await Mediator.Send(
|
||||
// new DeleteIdentityCommand() { Guid = uuid },
|
||||
// cancellationToken);
|
||||
// return StatusCode(StatusCodes.Status204NoContent);
|
||||
// }
|
||||
[HttpDelete("accounts/{uuid:guid}")]
|
||||
[SwaggerOperation("Delete an account")]
|
||||
[SwaggerResponse(StatusCodes.Status204NoContent, "Request successful")]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status400BadRequest, "Input data validation error",
|
||||
typeof(HttpValidationProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status401Unauthorized, "Unauthorized to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status403Forbidden,
|
||||
"Not enough privileges to perform an action",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status404NotFound, "Object not found",
|
||||
typeof(ProblemDetails))]
|
||||
[SwaggerResponse(
|
||||
StatusCodes.Status500InternalServerError, "Internal server error",
|
||||
typeof(ProblemDetails))]
|
||||
public async Task<IActionResult> DeleteAccount(
|
||||
[FromRoute] Guid uuid,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
await Mediator.Send(
|
||||
new DeleteAccountCommand() { Guid = uuid },
|
||||
cancellationToken);
|
||||
return StatusCode(StatusCodes.Status204NoContent);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user