Responsividade Mobile
This commit is contained in:
parent
e6cd510a29
commit
5101c3665a
|
|
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Authorization;
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace line_gestao_api.Controllers;
|
||||
|
||||
|
|
@ -293,6 +294,95 @@ public class UsersController : ControllerBase
|
|||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Roles = "admin")]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
if (_tenantProvider.TenantId == null)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
var currentUserId = GetCurrentUserId();
|
||||
if (currentUserId.HasValue && currentUserId.Value == id)
|
||||
{
|
||||
return BadRequest(new ValidationErrorResponse
|
||||
{
|
||||
Errors = new List<ValidationErrorDto>
|
||||
{
|
||||
new() { Field = "usuario", Message = "Você não pode excluir a própria conta." }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var tenantId = _tenantProvider.TenantId.Value;
|
||||
var user = await _userManager.Users.FirstOrDefaultAsync(u => u.Id == id && u.TenantId == tenantId);
|
||||
if (user == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if (user.IsActive)
|
||||
{
|
||||
return BadRequest(new ValidationErrorResponse
|
||||
{
|
||||
Errors = new List<ValidationErrorDto>
|
||||
{
|
||||
new() { Field = "usuario", Message = "Inative a conta antes de excluir permanentemente." }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var targetRoles = await _userManager.GetRolesAsync(user);
|
||||
var isAdmin = targetRoles.Any(r => string.Equals(r, "admin", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (isAdmin)
|
||||
{
|
||||
var adminRoleId = await _roleManager.Roles
|
||||
.Where(r => r.Name == "admin")
|
||||
.Select(r => (Guid?)r.Id)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (adminRoleId.HasValue)
|
||||
{
|
||||
var hasAnotherAdmin = await (
|
||||
from ur in _db.UserRoles
|
||||
join u in _userManager.Users on ur.UserId equals u.Id
|
||||
where ur.RoleId == adminRoleId.Value
|
||||
&& u.TenantId == tenantId
|
||||
&& u.Id != id
|
||||
select u.Id
|
||||
).AnyAsync();
|
||||
|
||||
if (!hasAnotherAdmin)
|
||||
{
|
||||
return BadRequest(new ValidationErrorResponse
|
||||
{
|
||||
Errors = new List<ValidationErrorDto>
|
||||
{
|
||||
new() { Field = "usuario", Message = "Não é permitido excluir o último administrador." }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var deleteResult = await _userManager.DeleteAsync(user);
|
||||
if (!deleteResult.Succeeded)
|
||||
{
|
||||
return BadRequest(new ValidationErrorResponse
|
||||
{
|
||||
Errors = deleteResult.Errors.Select(e => new ValidationErrorDto
|
||||
{
|
||||
Field = "usuario",
|
||||
Message = e.Description
|
||||
}).ToList()
|
||||
});
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
private static List<ValidationErrorDto> ValidateCreate(UserCreateRequest req)
|
||||
{
|
||||
var errors = new List<ValidationErrorDto>();
|
||||
|
|
@ -382,4 +472,10 @@ public class UsersController : ControllerBase
|
|||
|
||||
return errors;
|
||||
}
|
||||
|
||||
private Guid? GetCurrentUserId()
|
||||
{
|
||||
var raw = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub");
|
||||
return Guid.TryParse(raw, out var parsed) ? parsed : null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ builder.Services.AddIdentityCore<ApplicationUser>(options =>
|
|||
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
|
||||
})
|
||||
.AddRoles<IdentityRole<Guid>>()
|
||||
.AddErrorDescriber<PortugueseIdentityErrorDescriber>()
|
||||
.AddEntityFrameworkStores<AppDbContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
namespace line_gestao_api.Services;
|
||||
|
||||
public class PortugueseIdentityErrorDescriber : IdentityErrorDescriber
|
||||
{
|
||||
public override IdentityError DefaultError()
|
||||
=> NewError(nameof(DefaultError), "Ocorreu uma falha desconhecida.");
|
||||
|
||||
public override IdentityError ConcurrencyFailure()
|
||||
=> NewError(nameof(ConcurrencyFailure), "Falha de concorrência. O registro foi alterado por outro processo.");
|
||||
|
||||
public override IdentityError PasswordMismatch()
|
||||
=> NewError(nameof(PasswordMismatch), "Senha incorreta.");
|
||||
|
||||
public override IdentityError InvalidToken()
|
||||
=> NewError(nameof(InvalidToken), "Token inválido.");
|
||||
|
||||
public override IdentityError LoginAlreadyAssociated()
|
||||
=> NewError(nameof(LoginAlreadyAssociated), "Este login já está associado a outra conta.");
|
||||
|
||||
public override IdentityError InvalidUserName(string? userName)
|
||||
=> NewError(nameof(InvalidUserName), $"Nome de usuário '{userName}' é inválido. Use apenas letras e números.");
|
||||
|
||||
public override IdentityError InvalidEmail(string? email)
|
||||
=> NewError(nameof(InvalidEmail), $"E-mail '{email}' é inválido.");
|
||||
|
||||
public override IdentityError DuplicateUserName(string userName)
|
||||
=> NewError(nameof(DuplicateUserName), $"O nome de usuário '{userName}' já está em uso.");
|
||||
|
||||
public override IdentityError DuplicateEmail(string email)
|
||||
=> NewError(nameof(DuplicateEmail), $"O e-mail '{email}' já está em uso.");
|
||||
|
||||
public override IdentityError InvalidRoleName(string? role)
|
||||
=> NewError(nameof(InvalidRoleName), $"O nome da permissão '{role}' é inválido.");
|
||||
|
||||
public override IdentityError DuplicateRoleName(string role)
|
||||
=> NewError(nameof(DuplicateRoleName), $"A permissão '{role}' já existe.");
|
||||
|
||||
public override IdentityError UserAlreadyHasPassword()
|
||||
=> NewError(nameof(UserAlreadyHasPassword), "Este usuário já possui senha definida.");
|
||||
|
||||
public override IdentityError UserLockoutNotEnabled()
|
||||
=> NewError(nameof(UserLockoutNotEnabled), "Bloqueio não está habilitado para este usuário.");
|
||||
|
||||
public override IdentityError UserAlreadyInRole(string role)
|
||||
=> NewError(nameof(UserAlreadyInRole), $"O usuário já possui a permissão '{role}'.");
|
||||
|
||||
public override IdentityError UserNotInRole(string role)
|
||||
=> NewError(nameof(UserNotInRole), $"O usuário não possui a permissão '{role}'.");
|
||||
|
||||
public override IdentityError PasswordTooShort(int length)
|
||||
=> NewError(nameof(PasswordTooShort), $"A senha deve ter pelo menos {length} caracteres.");
|
||||
|
||||
public override IdentityError PasswordRequiresNonAlphanumeric()
|
||||
=> NewError(nameof(PasswordRequiresNonAlphanumeric), "A senha deve conter pelo menos um caractere especial.");
|
||||
|
||||
public override IdentityError PasswordRequiresDigit()
|
||||
=> NewError(nameof(PasswordRequiresDigit), "A senha deve conter pelo menos um número ('0'-'9').");
|
||||
|
||||
public override IdentityError PasswordRequiresLower()
|
||||
=> NewError(nameof(PasswordRequiresLower), "A senha deve conter pelo menos uma letra minúscula ('a'-'z').");
|
||||
|
||||
public override IdentityError PasswordRequiresUpper()
|
||||
=> NewError(nameof(PasswordRequiresUpper), "A senha deve conter pelo menos uma letra maiúscula ('A'-'Z').");
|
||||
|
||||
public override IdentityError PasswordRequiresUniqueChars(int uniqueChars)
|
||||
=> NewError(nameof(PasswordRequiresUniqueChars), $"A senha deve usar pelo menos {uniqueChars} caracteres diferentes.");
|
||||
|
||||
public override IdentityError RecoveryCodeRedemptionFailed()
|
||||
=> NewError(nameof(RecoveryCodeRedemptionFailed), "Código de recuperação inválido.");
|
||||
|
||||
private static IdentityError NewError(string code, string description)
|
||||
=> new() { Code = code, Description = description };
|
||||
}
|
||||
Loading…
Reference in New Issue