summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Controllers/AdministratorSessionsController.cs6
-rw-r--r--Controllers/AdministratorsController.cs37
-rw-r--r--Forms/UserAccountForm.cs3
-rw-r--r--Logics/BaseUserAccountLogic.cs31
-rw-r--r--Logics/CreateAdministratorLogic.cs37
-rw-r--r--Logics/CreateAdministratorSessionLogic.cs18
-rw-r--r--Program.cs4
-rw-r--r--Services/IUserAccountService.cs8
-rw-r--r--Services/TokenGenerator.cs2
-rw-r--r--Services/UserAccountService.cs21
10 files changed, 148 insertions, 19 deletions
diff --git a/Controllers/AdministratorSessionsController.cs b/Controllers/AdministratorSessionsController.cs
index 2ecf5e0..87f3034 100644
--- a/Controllers/AdministratorSessionsController.cs
+++ b/Controllers/AdministratorSessionsController.cs
@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BackendPIA.Forms;
using BackendPIA.Models;
@@ -10,12 +12,10 @@ namespace BackendPIA.Controllers {
[Route("api/admin")]
[ApiController]
public class AdministratorSessionsController : ControllerBase {
- private readonly ApplicationDbContext _context;
private readonly ITokenGenerator _token_generator;
private readonly UserManager<UserAccount> _manager;
- public AdministratorSessionsController(ApplicationDbContext context, ITokenGenerator token_generator, UserManager<UserAccount> manager) {
- _context = context;
+ public AdministratorSessionsController(ITokenGenerator token_generator, UserManager<UserAccount> manager) {
_token_generator = token_generator;
_manager = manager;
}
diff --git a/Controllers/AdministratorsController.cs b/Controllers/AdministratorsController.cs
new file mode 100644
index 0000000..66f805c
--- /dev/null
+++ b/Controllers/AdministratorsController.cs
@@ -0,0 +1,37 @@
+using AutoMapper;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Mvc;
+using BackendPIA.Forms;
+using BackendPIA.Models;
+using BackendPIA.Services;
+using BackendPIA.Errors;
+using BackendPIA.Logics;
+
+namespace BackendPIA.Controllers {
+ [Route("api/admin")]
+ [ApiController]
+ public class AdministratorsController : ControllerBase {
+ private readonly IUserAccountService _user_account_service;
+ private readonly IMapper _mapper;
+ private readonly ITokenGenerator _token_generator;
+ private readonly UserManager<UserAccount> _manager;
+
+ public AdministratorsController(UserManager<UserAccount> manager, IUserAccountService user_account_service, ITokenGenerator token_generator, IMapper mapper) {
+ _user_account_service = user_account_service;
+ _mapper = mapper;
+ _manager = manager;
+ _token_generator = token_generator;
+ }
+
+ [HttpPost("signup")]
+ public async Task<ActionResult<AuthenticationToken>> Create(UserAccountForm form) {
+ CreateAdministratorLogic logic = new CreateAdministratorLogic(_token_generator, _manager, form, _mapper, _user_account_service);
+ var result = await logic.Call();
+
+ if(result)
+ return Ok(logic.Token);
+
+ return StatusCode(422, logic.Errors);
+ }
+ }
+} \ No newline at end of file
diff --git a/Forms/UserAccountForm.cs b/Forms/UserAccountForm.cs
index f513a3a..cac96d4 100644
--- a/Forms/UserAccountForm.cs
+++ b/Forms/UserAccountForm.cs
@@ -1,4 +1,6 @@
using System.ComponentModel.DataAnnotations;
+using AutoMapper.Configuration.Annotations;
+
namespace BackendPIA.Forms {
public class UserAccountForm {
@@ -9,6 +11,7 @@ namespace BackendPIA.Forms {
public string? UserName { get; set; }
[Required]
+ [Ignore]
public string? Password { get; set; }
}
} \ No newline at end of file
diff --git a/Logics/BaseUserAccountLogic.cs b/Logics/BaseUserAccountLogic.cs
new file mode 100644
index 0000000..1686bb6
--- /dev/null
+++ b/Logics/BaseUserAccountLogic.cs
@@ -0,0 +1,31 @@
+using Microsoft.AspNetCore.Identity;
+using BackendPIA.Services;
+using BackendPIA.Forms;
+using BackendPIA.Models;
+
+namespace BackendPIA.Logics {
+ public abstract class BaseUserAccountLogic {
+ protected readonly ITokenGenerator _token_generator;
+ protected readonly UserManager<UserAccount> _manager;
+ protected AuthenticationToken? _token;
+ public AuthenticationToken? Token { get { return _token; } }
+
+ public BaseUserAccountLogic(ITokenGenerator token_generator, UserManager<UserAccount> manager) {
+ _manager = manager;
+ _token_generator = token_generator;
+ }
+
+ protected async Task SetAuthenticationToken(UserAccount user) {
+ _token = new AuthenticationToken { Token = _token_generator.Generate(user, "administrator"),
+ RefreshToken = _token_generator.GenerateRefreshToken() };
+ await SetUserRefreshToken(user);
+ }
+
+ // We overwrite or set the value of the session token in the database: all other previous logins are invalid.
+ private async Task SetUserRefreshToken(UserAccount user) {
+ user.SessionToken = _token.RefreshToken;
+ user.SessionTokenExpiryTime = DateTime.UtcNow.AddHours(3);
+ await _manager.UpdateAsync(user);
+ }
+ }
+} \ No newline at end of file
diff --git a/Logics/CreateAdministratorLogic.cs b/Logics/CreateAdministratorLogic.cs
new file mode 100644
index 0000000..9f8e573
--- /dev/null
+++ b/Logics/CreateAdministratorLogic.cs
@@ -0,0 +1,37 @@
+using AutoMapper;
+using Microsoft.AspNetCore.Identity;
+using BackendPIA.Services;
+using BackendPIA.Models;
+using BackendPIA.Forms;
+
+namespace BackendPIA.Logics{
+ public class CreateAdministratorLogic : BaseUserAccountLogic {
+ private readonly UserAccountForm _form;
+ private readonly IMapper _mapper;
+ private readonly IUserAccountService _user_account_service;
+ private IEnumerable<IdentityError> _errors;
+ public IEnumerable<IdentityError> Errors { get => _errors; }
+
+ public CreateAdministratorLogic(ITokenGenerator token_generator, UserManager<UserAccount> manager, UserAccountForm form,
+ IMapper mapper, IUserAccountService service) : base(token_generator, manager)
+ {
+ _form = form;
+ _mapper = mapper;
+ _user_account_service = service;
+ }
+
+ public async Task<bool> Call() {
+ UserAccount user = _mapper.Map<UserAccount>(_form);
+ var result = await _user_account_service.CreateUserAccount(user, _form.Password, "Administrator");
+
+ if(result.Succeeded) {
+ SetAuthenticationToken(user);
+
+ return true;
+ }
+
+ _errors = result.Errors;
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/Logics/CreateAdministratorSessionLogic.cs b/Logics/CreateAdministratorSessionLogic.cs
index a7e1860..ce283c7 100644
--- a/Logics/CreateAdministratorSessionLogic.cs
+++ b/Logics/CreateAdministratorSessionLogic.cs
@@ -4,17 +4,10 @@ using BackendPIA.Models;
using BackendPIA.Forms;
namespace BackendPIA.Logics {
- public class CreateAdministratorSessionLogic {
- private readonly ITokenGenerator _token_generator;
- private readonly UserManager<UserAccount> _manager;
+ public class CreateAdministratorSessionLogic : BaseUserAccountLogic {
private readonly UserAccountLoginForm _form;
- private AuthenticationToken _token;
- public AuthenticationToken Token { get { return _token; } }
-
- public CreateAdministratorSessionLogic(ITokenGenerator token_generator, UserManager<UserAccount> manager, UserAccountLoginForm form) {
- _token_generator = token_generator;
- _manager = manager;
+ public CreateAdministratorSessionLogic(ITokenGenerator token_generator, UserManager<UserAccount> manager, UserAccountLoginForm form) : base(token_generator, manager) {
_form = form;
}
@@ -27,12 +20,7 @@ namespace BackendPIA.Logics {
var result = await _manager.CheckPasswordAsync(user, _form.Password);
if(result) {
- _token = new AuthenticationToken { Token = _token_generator.Generate(user, "administrator"),
- RefreshToken = _token_generator.GenerateRefreshToken() };
- // We overwrite or set the value of the session token in the database: all other previous logins are invalid.
- user.SessionToken = _token.RefreshToken;
- user.SessionTokenExpiryTime = DateTime.UtcNow.AddHours(3);
- await _manager.UpdateAsync(user);
+ SetAuthenticationToken(user);
return true;
}
diff --git a/Program.cs b/Program.cs
index 0bcd2cb..c3971ab 100644
--- a/Program.cs
+++ b/Program.cs
@@ -23,6 +23,7 @@ builder.Services.AddAutoMapper(typeof(Program));
// Custom services configuration.
builder.Services.AddSingleton<ITokenGenerator>(s => new TokenGenerator(builder.Configuration["Jwt:Key"]));
+builder.Services.AddSingleton<IUserAccountService, UserAccountService>();
// End of custom services configuration.
// Swagger configuration.
@@ -67,6 +68,9 @@ builder.Services.AddAuthentication(options => {
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero }
);
+builder.Services.AddAuthorization(options => {
+ options.AddPolicy("IsAdministrator", policy => policy.RequireClaim("administrator"));
+});
// End of authentication configuration.
// Identity configuration.
diff --git a/Services/IUserAccountService.cs b/Services/IUserAccountService.cs
new file mode 100644
index 0000000..900e562
--- /dev/null
+++ b/Services/IUserAccountService.cs
@@ -0,0 +1,8 @@
+using Microsoft.AspNetCore.Identity;
+using BackendPIA.Models;
+
+namespace BackendPIA.Services {
+ public interface IUserAccountService {
+ public Task<IdentityResult> CreateUserAccount(UserAccount user, string password, string role);
+ }
+} \ No newline at end of file
diff --git a/Services/TokenGenerator.cs b/Services/TokenGenerator.cs
index 3a99e09..70aca4a 100644
--- a/Services/TokenGenerator.cs
+++ b/Services/TokenGenerator.cs
@@ -16,7 +16,7 @@ namespace BackendPIA.Services {
public string Generate(UserAccount user, string role) {
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_key));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
- var expiration = DateTime.UtcNow.AddMinutes(20);
+ var expiration = DateTime.UtcNow.AddMinutes(1);
//var issuer = _configuration["Jwt:Issuer"];
var claims = new List<Claim> {
new Claim("sid", user.Id),
diff --git a/Services/UserAccountService.cs b/Services/UserAccountService.cs
new file mode 100644
index 0000000..e81ea76
--- /dev/null
+++ b/Services/UserAccountService.cs
@@ -0,0 +1,21 @@
+using Microsoft.AspNetCore.Identity;
+using BackendPIA.Models;
+
+namespace BackendPIA.Services {
+ public class UserAccountService : IUserAccountService {
+ private readonly UserManager<UserAccount> _manager;
+
+ public UserAccountService(UserManager<UserAccount> manager) {
+ _manager = manager;
+ }
+
+ public async Task<IdentityResult> CreateUserAccount(UserAccount user, string password, string role) {
+ var result = await _manager.CreateAsync(user, password);
+
+ if(result.Succeeded)
+ await _manager.AddToRoleAsync(user, role);
+
+ return result;
+ }
+ }
+} \ No newline at end of file