list of authorities, changing authority auth data
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
using Domains;
|
using Domains;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.GeneralExceptions;
|
namespace ApplicationLayer.GeneralExceptions;
|
||||||
|
|
||||||
/// Exception to throw when entity not found
|
/// Exception to throw when entity not found
|
||||||
/// <param name="id">Identifier of entity</param>
|
/// <param name="id">Identifier of entity</param>
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using ApplicationLayer.GeneralExceptions;
|
namespace ApplicationLayer.GeneralExceptions;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.GeneralExceptions;
|
|
||||||
|
|
||||||
/// Exception to throw when entity not found
|
/// Exception to throw when entity not found
|
||||||
public class EntityNotFoundException(string message) : ApiException(message);
|
public class EntityNotFoundException(string message) : ApiException(message);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using ApplicationLayer.Services.GeneralExceptions;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
using Domains.Users;
|
using Domains.Users;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Users.Exceptions;
|
namespace ApplicationLayer.Services.Users.Exceptions;
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Domains;
|
||||||
|
|
||||||
|
namespace ApplicationLayer.Services.Users.Models
|
||||||
|
{
|
||||||
|
/// Auth data with nullable password for making change auth data requests
|
||||||
|
public class ChangeAuthData
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
[MaxLength(ConfigurationConstraints.EmailLength)]
|
||||||
|
public string Email { get; set; } = null!;
|
||||||
|
|
||||||
|
[MaxLength(ConfigurationConstraints.PasswordLength)]
|
||||||
|
public string? Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using ApplicationLayer.Services.AuthServices.Common;
|
using ApplicationLayer.Services.Users.Models;
|
||||||
|
|
||||||
namespace ApplicationLayer.Services.Users.Requests;
|
namespace ApplicationLayer.Services.Users.Requests;
|
||||||
|
|
||||||
public class ChangeUserAuthDataRequest(Guid userId, AuthData newAuthData)
|
public class ChangeUserAuthDataRequest(Guid userId, ChangeAuthData newAuthData)
|
||||||
{
|
{
|
||||||
[Required] public Guid UserId { get; set; } = userId;
|
[Required] public Guid UserId { get; set; } = userId;
|
||||||
|
|
||||||
[Required] public AuthData NewAuthData { get; set; } = newAuthData;
|
[Required] public ChangeAuthData NewAuthData { get; set; } = newAuthData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Domains;
|
||||||
|
using FluentValidation;
|
||||||
|
|
||||||
|
namespace ApplicationLayer.Services.Users.Requests.Validation
|
||||||
|
{
|
||||||
|
public class ChangeUserAuthDataRequestValidator : AbstractValidator<ChangeUserAuthDataRequest>
|
||||||
|
{
|
||||||
|
public ChangeUserAuthDataRequestValidator()
|
||||||
|
{
|
||||||
|
RuleFor(r => r.NewAuthData)
|
||||||
|
.NotEmpty();
|
||||||
|
|
||||||
|
RuleFor(r => r.NewAuthData.Email)
|
||||||
|
.NotEmpty()
|
||||||
|
.EmailAddress()
|
||||||
|
.WithMessage("Email should be valid")
|
||||||
|
.MaximumLength(ConfigurationConstraints.EmailLength)
|
||||||
|
.WithMessage($"Email address length must be less than {ConfigurationConstraints.EmailLength}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
using ApplicationLayer.Services.Applicants.Models;
|
using ApplicationLayer.Services.Applicants.Models;
|
||||||
using ApplicationLayer.Services.Applicants.NeededServices;
|
using ApplicationLayer.Services.Applicants.NeededServices;
|
||||||
using ApplicationLayer.Services.AuthServices.Common;
|
|
||||||
using ApplicationLayer.Services.AuthServices.NeededServices;
|
using ApplicationLayer.Services.AuthServices.NeededServices;
|
||||||
using ApplicationLayer.Services.Users.Exceptions;
|
using ApplicationLayer.Services.Users.Exceptions;
|
||||||
using ApplicationLayer.Services.Users.Models;
|
using ApplicationLayer.Services.Users.Models;
|
||||||
@@ -53,10 +52,10 @@ public class UsersService(
|
|||||||
/// <param name="user">User to remove</param>
|
/// <param name="user">User to remove</param>
|
||||||
/// <param name="authData">New auth data</param>
|
/// <param name="authData">New auth data</param>
|
||||||
/// <param name="cancellationToken">Cancellation token</param>
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
private async Task ChangeAccountAuthDataAsync(User user, AuthData authData, CancellationToken cancellationToken)
|
private async Task ChangeAccountAuthDataAsync(User user, ChangeAuthData authData, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
user.Email = authData.Email;
|
user.Email = authData.Email;
|
||||||
user.Password = authData.Password;
|
user.Password = authData.Password ?? user.Password;
|
||||||
await users.UpdateAsync(user, cancellationToken);
|
await users.UpdateAsync(user, cancellationToken);
|
||||||
|
|
||||||
await unitOfWork.SaveAsync(cancellationToken);
|
await unitOfWork.SaveAsync(cancellationToken);
|
||||||
|
|||||||
@@ -49,6 +49,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Logout()
|
||||||
|
{
|
||||||
|
Client.AuthToken = null;
|
||||||
|
AuthData = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UserDataProvider.UpdateCurrentRole();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorHandler.Handle(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///Re-auth if token expired or something
|
///Re-auth if token expired or something
|
||||||
public async Task ReAuthenticate()
|
public async Task ReAuthenticate()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,21 +20,27 @@ namespace BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvide
|
|||||||
|
|
||||||
public void UpdateCurrentRole()
|
public void UpdateCurrentRole()
|
||||||
{
|
{
|
||||||
|
var role = CurrentRole;
|
||||||
|
|
||||||
if (client.AuthToken is null)
|
if (client.AuthToken is null)
|
||||||
{
|
{
|
||||||
CurrentRole = null;
|
if (CurrentRole is not null)
|
||||||
return;
|
{
|
||||||
|
role = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
var token = tokenHandler.ReadJwtToken(client.AuthToken.Token);
|
|
||||||
var role = token.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.Role)?.Value;
|
|
||||||
|
|
||||||
switch (role)
|
|
||||||
{
|
{
|
||||||
case Constants.ApplicantRole: break;
|
var token = tokenHandler.ReadJwtToken(client.AuthToken.Token);
|
||||||
case Constants.ApprovingAuthorityRole: break;
|
role = token.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.Role)?.Value;
|
||||||
case Constants.AdminRole: break;
|
|
||||||
default: throw new UnknownRoleException();
|
switch (role)
|
||||||
|
{
|
||||||
|
case Constants.ApplicantRole: break;
|
||||||
|
case Constants.ApprovingAuthorityRole: break;
|
||||||
|
case Constants.AdminRole: break;
|
||||||
|
default: throw new UnknownRoleException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CurrentRole != role)
|
if (CurrentRole != role)
|
||||||
|
|||||||
@@ -1,12 +1,41 @@
|
|||||||
@inherits LayoutComponentBase
|
@using BlazorWebAssemblyVisaApiClient.Components.Auth
|
||||||
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider
|
||||||
|
@inherits LayoutComponentBase
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<NavMenu/>
|
<NavMenu/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main>
|
<main class="fullscreen">
|
||||||
<article class="content px-4 fullscreen">
|
<div class="top-row px-4">
|
||||||
|
<AuthComponent @ref="authComponent"/>
|
||||||
|
@if (UserDataProvider.CurrentRole is not null)
|
||||||
|
{
|
||||||
|
<p>
|
||||||
|
Logged as @UserDataProvider.CurrentRole (@AuthComponent.AuthData?.Email)
|
||||||
|
<button class="btn-secondary" @onclick="authComponent.Logout">Log out</button>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<NavLink href="/">Log in</NavLink>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<article class="content px-4">
|
||||||
@Body
|
@Body
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private AuthComponent authComponent = null!;
|
||||||
|
|
||||||
|
[Inject] private IUserDataProvider UserDataProvider { get; set; } = null!;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
UserDataProvider.OnRoleChanged += StateHasChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
@if(UserDataProvider.CurrentRole is Constants.ApplicantRole)
|
@if (UserDataProvider.CurrentRole is Constants.ApplicantRole)
|
||||||
{
|
{
|
||||||
<nav class="flex-column">
|
<nav class="flex-column">
|
||||||
<div class="nav-item px-3">
|
<div class="nav-item px-3">
|
||||||
@@ -36,6 +36,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
}
|
}
|
||||||
|
@if (UserDataProvider.CurrentRole is Constants.AdminRole)
|
||||||
|
{
|
||||||
|
<nav class="flex-column">
|
||||||
|
<div class="nav-item px-3">
|
||||||
|
<NavLink class="nav-link" href="authorities" Match="NavLinkMatch.All">
|
||||||
|
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Authorities
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@page "/applications/{ApplicationId}"
|
@page "/applications/{ApplicationId}"
|
||||||
|
@using System.Net
|
||||||
@using BlazorWebAssemblyVisaApiClient.Common.Exceptions
|
@using BlazorWebAssemblyVisaApiClient.Common.Exceptions
|
||||||
@using BlazorWebAssemblyVisaApiClient.Components
|
@using BlazorWebAssemblyVisaApiClient.Components
|
||||||
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
||||||
@@ -210,6 +211,11 @@
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (e is ApiException<ProblemDetails> { Result.Status: (int)HttpStatusCode.Conflict })
|
||||||
|
{
|
||||||
|
Nav.NavigateTo("/applications");
|
||||||
|
}
|
||||||
ErrorHandler.Handle(e);
|
ErrorHandler.Handle(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
@page "/authorities"
|
||||||
|
@using VisaApiClient
|
||||||
|
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
||||||
|
|
||||||
|
<table class="table table-bordered table-hover">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Email</th><th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var authority in authorities)
|
||||||
|
{
|
||||||
|
var path = $"authorities/{authority.Id}/{authority.Email}";
|
||||||
|
<tr>
|
||||||
|
<td>@authority.Email</td>
|
||||||
|
<td>
|
||||||
|
<NavLink href="@path">
|
||||||
|
<button class="btn-outline-primary">Change</button>
|
||||||
|
</NavLink>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private IEnumerable<UserModel> authorities = [];
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
authorities = await Client.GetAuthorityAccountsAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorHandler.Handle(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
@page "/authorities/{authorityId}/{oldEmail}"
|
||||||
|
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
||||||
|
@using BlazorWebAssemblyVisaApiClient.Common.Exceptions
|
||||||
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Services.UserDataProvider
|
||||||
|
@using VisaApiClient
|
||||||
|
@using BlazorWebAssemblyVisaApiClient.Components
|
||||||
|
@using BlazorWebAssemblyVisaApiClient.Infrastructure.Helpers
|
||||||
|
@using FluentValidation
|
||||||
|
|
||||||
|
<EditForm Model="model" class="with-centered-content">
|
||||||
|
<div >
|
||||||
|
<label>
|
||||||
|
New email:<br/>
|
||||||
|
<InputText class="rounded" @bind-Value="model.Email"/>
|
||||||
|
</label><br/><p/>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
New password (leave blank if shouldn't be changed):<br/>
|
||||||
|
<InputText class="rounded" @bind-Value="model.Password"/>
|
||||||
|
</label><br/><p/>
|
||||||
|
|
||||||
|
<button class="btn-primary rounded" @onclick="Save">Save</button><br/>
|
||||||
|
<Status @ref="status"/>
|
||||||
|
</div>
|
||||||
|
</EditForm>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private Status status = null!;
|
||||||
|
private ChangeAuthData model = new();
|
||||||
|
|
||||||
|
[Parameter] public string AuthorityId { get; set; } = null!;
|
||||||
|
|
||||||
|
[Parameter] public string OldEmail { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject] private IUserDataProvider UserDataProvider { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject] private IValidator<ChangeUserAuthDataRequest> ChangeUserAuthDataRequestValidator { get; set; } = null!;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (UserDataProvider.CurrentRole is not Constants.AdminRole)
|
||||||
|
{
|
||||||
|
throw new NotLoggedInException();
|
||||||
|
}
|
||||||
|
|
||||||
|
model.Email = OldEmail;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorHandler.Handle(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Save()
|
||||||
|
{
|
||||||
|
var request = new ChangeUserAuthDataRequest
|
||||||
|
{
|
||||||
|
UserId = Guid.Parse(AuthorityId),
|
||||||
|
NewAuthData = model
|
||||||
|
};
|
||||||
|
|
||||||
|
var validationResult = await ChangeUserAuthDataRequestValidator.ValidateAsync(request);
|
||||||
|
if (!validationResult.IsValid)
|
||||||
|
{
|
||||||
|
status.SetError(validationResult.ToErrorsString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
status.SetMessage("Wait...");
|
||||||
|
await Client.ChangeAuthorityAuthDataAsync(request);
|
||||||
|
status.SetSuccess("Success");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ErrorHandler.Handle(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
</label><br/>
|
</label><br/>
|
||||||
<ValidationMessage For="() => editableVisa.ExpirationDate"></ValidationMessage><br/>
|
<ValidationMessage For="() => editableVisa.ExpirationDate"></ValidationMessage><br/>
|
||||||
|
|
||||||
<input type="button" class="btn-outline-primary"
|
<input type="button" class="btn-outline-primary rounded"
|
||||||
disabled="@(requestModel.PastVisas.Count == ConfigurationConstraints.MaxPastVisas)"
|
disabled="@(requestModel.PastVisas.Count == ConfigurationConstraints.MaxPastVisas)"
|
||||||
@onclick="AddPastVisa" value="Add"/>
|
@onclick="AddPastVisa" value="Add"/>
|
||||||
<Status @ref="pastVisaStatus"/>
|
<Status @ref="pastVisaStatus"/>
|
||||||
@@ -157,7 +157,7 @@
|
|||||||
</label><br/>
|
</label><br/>
|
||||||
<ValidationMessage For="() => editableVisit.EndDate"></ValidationMessage><br/>
|
<ValidationMessage For="() => editableVisit.EndDate"></ValidationMessage><br/>
|
||||||
|
|
||||||
<input type="button" class="btn-outline-primary"
|
<input type="button" class="btn-outline-primary rounded"
|
||||||
disabled="@(requestModel.PastVisits.Count == ConfigurationConstraints.MaxPastVisits)"
|
disabled="@(requestModel.PastVisits.Count == ConfigurationConstraints.MaxPastVisits)"
|
||||||
@onclick="AddPastVisit" value="Add"/>
|
@onclick="AddPastVisit" value="Add"/>
|
||||||
<Status @ref="pastVisitStatus"/>
|
<Status @ref="pastVisitStatus"/>
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
<br/><input type="submit" class="btn-outline-primary" value="Register"/>
|
<br/><input type="submit" class="btn-outline-primary rounded" value="Register"/>
|
||||||
<ValidationSummary/>
|
<ValidationSummary/>
|
||||||
<Status @ref="status"/>
|
<Status @ref="status"/>
|
||||||
</EditForm>
|
</EditForm>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using VisaApiClient;
|
using VisaApiClient;
|
||||||
|
|
||||||
namespace BlazorWebAssemblyVisaApiClient.Validation.Common;
|
namespace BlazorWebAssemblyVisaApiClient.Validation.Auth;
|
||||||
|
|
||||||
public class AuthDataValidator : AbstractValidator<AuthData>
|
public class AuthDataValidator : AbstractValidator<AuthData>
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using VisaApiClient;
|
||||||
|
|
||||||
|
namespace BlazorWebAssemblyVisaApiClient.Validation.Auth
|
||||||
|
{
|
||||||
|
public class ChangeUserAuthDataRequestValidator : AbstractValidator<ChangeUserAuthDataRequest>
|
||||||
|
{
|
||||||
|
public ChangeUserAuthDataRequestValidator()
|
||||||
|
{
|
||||||
|
RuleFor(r => r.NewAuthData)
|
||||||
|
.NotEmpty();
|
||||||
|
|
||||||
|
RuleFor(r => r.NewAuthData.Email)
|
||||||
|
.NotEmpty()
|
||||||
|
.EmailAddress()
|
||||||
|
.WithMessage("Email should be valid")
|
||||||
|
.MaximumLength(ConfigurationConstraints.EmailLength)
|
||||||
|
.WithMessage($"Email address length must be less than {ConfigurationConstraints.EmailLength}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using VisaApiClient;
|
using VisaApiClient;
|
||||||
|
|
||||||
namespace BlazorWebAssemblyVisaApiClient.Validation.Common;
|
namespace BlazorWebAssemblyVisaApiClient.Validation.Auth;
|
||||||
|
|
||||||
public class RegisterRequestValidator : AbstractValidator<RegisterRequestModel>
|
public class RegisterRequestValidator : AbstractValidator<RegisterRequestModel>
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using ApplicationLayer.Services.GeneralExceptions;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
|
|
||||||
namespace Infrastructure.Database.Applicants.Repositories.Exceptions;
|
namespace Infrastructure.Database.Applicants.Repositories.Exceptions;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using ApplicationLayer.InfrastructureServicesInterfaces;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
using ApplicationLayer.Services.GeneralExceptions;
|
using ApplicationLayer.InfrastructureServicesInterfaces;
|
||||||
using Domains;
|
using Domains;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ApplicationLayer.Services.GeneralExceptions;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
|
|
||||||
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions;
|
namespace Infrastructure.Database.VisaApplications.Repositories.Exceptions;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class UsersController(
|
|||||||
ILoginService loginService,
|
ILoginService loginService,
|
||||||
IUsersService usersService,
|
IUsersService usersService,
|
||||||
IValidator<RegisterApplicantRequest> registerApplicantRequestValidator,
|
IValidator<RegisterApplicantRequest> registerApplicantRequestValidator,
|
||||||
IValidator<AuthData> authDataValidator,
|
IValidator<ChangeUserAuthDataRequest> changeUserAuthDataRequestValidator,
|
||||||
IValidator<RegisterRequest> registerRequestValidator) : ControllerBase
|
IValidator<RegisterRequest> registerRequestValidator) : ControllerBase
|
||||||
{
|
{
|
||||||
/// <summary> Adds applicant with user account </summary>
|
/// <summary> Adds applicant with user account </summary>
|
||||||
@@ -60,7 +60,7 @@ public class UsersController(
|
|||||||
{
|
{
|
||||||
var loginRequest = new LoginRequest
|
var loginRequest = new LoginRequest
|
||||||
{
|
{
|
||||||
AuthData = new AuthData { Email = email, Password = password }
|
AuthData = new() { Email = email, Password = password }
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await loginService.LoginAsync(loginRequest, cancellationToken);
|
var result = await loginService.LoginAsync(loginRequest, cancellationToken);
|
||||||
@@ -82,18 +82,18 @@ public class UsersController(
|
|||||||
|
|
||||||
/// <summary> Changes authority's account authentication data </summary>
|
/// <summary> Changes authority's account authentication data </summary>
|
||||||
/// <remarks> Accessible only for admins </remarks>
|
/// <remarks> Accessible only for admins </remarks>
|
||||||
[HttpPut("authorities/{authorityAccountId:guid}")]
|
[HttpPut("authorities")]
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
[ProducesResponseType(StatusCodes.Status403Forbidden)]
|
||||||
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
|
||||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
[Authorize(policy: PolicyConstants.AdminPolicy)]
|
||||||
public async Task<IActionResult> ChangeAuthorityAuthData(Guid authorityAccountId, AuthData authData, CancellationToken cancellationToken)
|
public async Task<IActionResult> ChangeAuthorityAuthData(ChangeUserAuthDataRequest request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await authDataValidator.ValidateAndThrowAsync(authData, cancellationToken);
|
await changeUserAuthDataRequestValidator.ValidateAndThrowAsync(request, cancellationToken);
|
||||||
|
|
||||||
await usersService.ChangeAuthorityAuthDataAsync(new ChangeUserAuthDataRequest(authorityAccountId, authData), cancellationToken);
|
await usersService.ChangeAuthorityAuthDataAsync(request, cancellationToken);
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using ApplicationLayer.GeneralExceptions;
|
using ApplicationLayer.GeneralExceptions;
|
||||||
using ApplicationLayer.Services.AuthServices.LoginService.Exceptions;
|
using ApplicationLayer.Services.AuthServices.LoginService.Exceptions;
|
||||||
using ApplicationLayer.Services.GeneralExceptions;
|
|
||||||
using ApplicationLayer.Services.VisaApplications.Exceptions;
|
using ApplicationLayer.Services.VisaApplications.Exceptions;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|||||||
@@ -388,6 +388,134 @@ namespace VisaApiClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes authority's account authentication data
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Accessible only for admins
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>Success</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public virtual System.Threading.Tasks.Task ChangeAuthorityAuthDataAsync(ChangeUserAuthDataRequest? body)
|
||||||
|
{
|
||||||
|
return ChangeAuthorityAuthDataAsync(body, System.Threading.CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
||||||
|
/// <summary>
|
||||||
|
/// Changes authority's account authentication data
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Accessible only for admins
|
||||||
|
/// </remarks>
|
||||||
|
/// <returns>Success</returns>
|
||||||
|
/// <exception cref="ApiException">A server side error occurred.</exception>
|
||||||
|
public virtual async System.Threading.Tasks.Task ChangeAuthorityAuthDataAsync(ChangeUserAuthDataRequest? body, System.Threading.CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var client_ = _httpClient;
|
||||||
|
var disposeClient_ = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var request_ = await CreateHttpRequestMessageAsync(cancellationToken).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, JsonSerializerSettings);
|
||||||
|
var content_ = new System.Net.Http.StringContent(json_);
|
||||||
|
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
|
||||||
|
request_.Content = content_;
|
||||||
|
request_.Method = new System.Net.Http.HttpMethod("PUT");
|
||||||
|
|
||||||
|
var urlBuilder_ = new System.Text.StringBuilder();
|
||||||
|
if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
|
||||||
|
// Operation Path: "users/authorities"
|
||||||
|
urlBuilder_.Append("users/authorities");
|
||||||
|
|
||||||
|
await PrepareRequestAsync(client_, request_, urlBuilder_, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var url_ = urlBuilder_.ToString();
|
||||||
|
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
|
||||||
|
|
||||||
|
await PrepareRequestAsync(client_, request_, url_, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||||
|
var disposeResponse_ = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var headers_ = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.IEnumerable<string>>();
|
||||||
|
foreach (var item_ in response_.Headers)
|
||||||
|
headers_[item_.Key] = item_.Value;
|
||||||
|
if (response_.Content != null && response_.Content.Headers != null)
|
||||||
|
{
|
||||||
|
foreach (var item_ in response_.Content.Headers)
|
||||||
|
headers_[item_.Key] = item_.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ProcessResponseAsync(client_, response_, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var status_ = (int)response_.StatusCode;
|
||||||
|
if (status_ == 200)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 404)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ProblemDetails>("Not Found", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 403)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ProblemDetails>("Forbidden", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 401)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ProblemDetails>("Unauthorized", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (status_ == 400)
|
||||||
|
{
|
||||||
|
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
||||||
|
if (objectResponse_.Object == null)
|
||||||
|
{
|
||||||
|
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
||||||
|
}
|
||||||
|
throw new ApiException<ProblemDetails>("Bad Request", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeResponse_)
|
||||||
|
response_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (disposeClient_)
|
||||||
|
client_.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns JWT-token for authentication
|
/// Returns JWT-token for authentication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -492,138 +620,6 @@ namespace VisaApiClient
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Changes authority's account authentication data
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Accessible only for admins
|
|
||||||
/// </remarks>
|
|
||||||
/// <returns>Success</returns>
|
|
||||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
|
||||||
public virtual System.Threading.Tasks.Task ChangeAuthorityAuthDataAsync(System.Guid authorityAccountId, AuthData? body)
|
|
||||||
{
|
|
||||||
return ChangeAuthorityAuthDataAsync(authorityAccountId, body, System.Threading.CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
|
|
||||||
/// <summary>
|
|
||||||
/// Changes authority's account authentication data
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Accessible only for admins
|
|
||||||
/// </remarks>
|
|
||||||
/// <returns>Success</returns>
|
|
||||||
/// <exception cref="ApiException">A server side error occurred.</exception>
|
|
||||||
public virtual async System.Threading.Tasks.Task ChangeAuthorityAuthDataAsync(System.Guid authorityAccountId, AuthData? body, System.Threading.CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
if (authorityAccountId == null)
|
|
||||||
throw new System.ArgumentNullException("authorityAccountId");
|
|
||||||
|
|
||||||
var client_ = _httpClient;
|
|
||||||
var disposeClient_ = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var request_ = await CreateHttpRequestMessageAsync(cancellationToken).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, JsonSerializerSettings);
|
|
||||||
var content_ = new System.Net.Http.StringContent(json_);
|
|
||||||
content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json");
|
|
||||||
request_.Content = content_;
|
|
||||||
request_.Method = new System.Net.Http.HttpMethod("PUT");
|
|
||||||
|
|
||||||
var urlBuilder_ = new System.Text.StringBuilder();
|
|
||||||
if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl);
|
|
||||||
// Operation Path: "users/authorities/{authorityAccountId}"
|
|
||||||
urlBuilder_.Append("users/authorities/");
|
|
||||||
urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(authorityAccountId, System.Globalization.CultureInfo.InvariantCulture)));
|
|
||||||
|
|
||||||
await PrepareRequestAsync(client_, request_, urlBuilder_, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var url_ = urlBuilder_.ToString();
|
|
||||||
request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);
|
|
||||||
|
|
||||||
await PrepareRequestAsync(client_, request_, url_, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
|
||||||
var disposeResponse_ = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var headers_ = new System.Collections.Generic.Dictionary<string, System.Collections.Generic.IEnumerable<string>>();
|
|
||||||
foreach (var item_ in response_.Headers)
|
|
||||||
headers_[item_.Key] = item_.Value;
|
|
||||||
if (response_.Content != null && response_.Content.Headers != null)
|
|
||||||
{
|
|
||||||
foreach (var item_ in response_.Content.Headers)
|
|
||||||
headers_[item_.Key] = item_.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
await ProcessResponseAsync(client_, response_, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
var status_ = (int)response_.StatusCode;
|
|
||||||
if (status_ == 200)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (status_ == 404)
|
|
||||||
{
|
|
||||||
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
|
||||||
if (objectResponse_.Object == null)
|
|
||||||
{
|
|
||||||
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
|
||||||
}
|
|
||||||
throw new ApiException<ProblemDetails>("Not Found", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (status_ == 403)
|
|
||||||
{
|
|
||||||
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
|
||||||
if (objectResponse_.Object == null)
|
|
||||||
{
|
|
||||||
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
|
||||||
}
|
|
||||||
throw new ApiException<ProblemDetails>("Forbidden", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (status_ == 401)
|
|
||||||
{
|
|
||||||
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
|
||||||
if (objectResponse_.Object == null)
|
|
||||||
{
|
|
||||||
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
|
||||||
}
|
|
||||||
throw new ApiException<ProblemDetails>("Unauthorized", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (status_ == 400)
|
|
||||||
{
|
|
||||||
var objectResponse_ = await ReadObjectResponseAsync<ProblemDetails>(response_, headers_, cancellationToken).ConfigureAwait(false);
|
|
||||||
if (objectResponse_.Object == null)
|
|
||||||
{
|
|
||||||
throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
|
|
||||||
}
|
|
||||||
throw new ApiException<ProblemDetails>("Bad Request", status_, objectResponse_.Text, headers_, objectResponse_.Object, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (disposeResponse_)
|
|
||||||
response_.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (disposeClient_)
|
|
||||||
client_.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes authority's account
|
/// Removes authority's account
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1979,6 +1975,33 @@ namespace VisaApiClient
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")]
|
||||||
|
public partial class ChangeAuthData
|
||||||
|
{
|
||||||
|
[Newtonsoft.Json.JsonProperty("email", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required]
|
||||||
|
[System.ComponentModel.DataAnnotations.StringLength(254, MinimumLength = 1)]
|
||||||
|
public string Email { get; set; } = default!;
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("password", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
|
||||||
|
[System.ComponentModel.DataAnnotations.StringLength(50)]
|
||||||
|
public string? Password { get; set; } = default!;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")]
|
||||||
|
public partial class ChangeUserAuthDataRequest
|
||||||
|
{
|
||||||
|
[Newtonsoft.Json.JsonProperty("userId", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required(AllowEmptyStrings = true)]
|
||||||
|
public System.Guid UserId { get; set; } = default!;
|
||||||
|
|
||||||
|
[Newtonsoft.Json.JsonProperty("newAuthData", Required = Newtonsoft.Json.Required.Always)]
|
||||||
|
[System.ComponentModel.DataAnnotations.Required]
|
||||||
|
public ChangeAuthData NewAuthData { get; set; } = new ChangeAuthData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")]
|
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.1.0.0 (NJsonSchema v11.0.2.0 (Newtonsoft.Json v13.0.0.0))")]
|
||||||
public enum Gender
|
public enum Gender
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user