From d34b1ec68e8a90c80f8fe2cd761440777568612e Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Tue, 11 Jun 2024 21:54:18 +0200 Subject: [PATCH] Code style refactor --- .editorconfig | 5 ++ src/AliasDb/AliasDbContext.cs | 2 +- src/AliasDb/AspNetUserRefreshTokens.cs | 2 +- src/AliasDb/Login.cs | 2 +- src/AliasVault.Api/AliasVault.Api.csproj | 1 + .../Controllers/AliasController.cs | 11 +++- .../Controllers/AuthController.cs | 65 ++++++++++++++----- .../AuthenticatedRequestController.cs | 13 ++-- .../Controllers/IdentityController.cs | 18 ++++- src/AliasVault.Api/Program.cs | 57 ++++++++-------- 10 files changed, 118 insertions(+), 58 deletions(-) diff --git a/.editorconfig b/.editorconfig index 3bc03fa1..0968faee 100644 --- a/.editorconfig +++ b/.editorconfig @@ -29,6 +29,11 @@ csharp_style_expression_bodied_accessors = true:silent csharp_style_expression_bodied_lambdas = true:silent csharp_style_expression_bodied_local_functions = false:silent dotnet_diagnostic.SA1011.severity = none +dotnet_diagnostic.SA1101.severity = none +dotnet_diagnostic.SA1200.severity = none +dotnet_diagnostic.SA1309.severity = none +dotnet_diagnostic.SA1310.severity = warning +dotnet_diagnostic.SX1309.severity = none # Razor files [*.razor] diff --git a/src/AliasDb/AliasDbContext.cs b/src/AliasDb/AliasDbContext.cs index 3051e890..0525e09e 100644 --- a/src/AliasDb/AliasDbContext.cs +++ b/src/AliasDb/AliasDbContext.cs @@ -6,8 +6,8 @@ //----------------------------------------------------------------------- namespace AliasDb; -using Microsoft.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; /// /// The AliasDbContext class. diff --git a/src/AliasDb/AspNetUserRefreshTokens.cs b/src/AliasDb/AspNetUserRefreshTokens.cs index 209b00d7..98eaae90 100644 --- a/src/AliasDb/AspNetUserRefreshTokens.cs +++ b/src/AliasDb/AspNetUserRefreshTokens.cs @@ -6,9 +6,9 @@ //----------------------------------------------------------------------- namespace AliasDb; -using Microsoft.AspNetCore.Identity; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.AspNetCore.Identity; /// /// Refresh tokens for users. diff --git a/src/AliasDb/Login.cs b/src/AliasDb/Login.cs index aa54991a..8695d935 100644 --- a/src/AliasDb/Login.cs +++ b/src/AliasDb/Login.cs @@ -6,9 +6,9 @@ //----------------------------------------------------------------------- namespace AliasDb; -using Microsoft.AspNetCore.Identity; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.AspNetCore.Identity; /// /// Login object. diff --git a/src/AliasVault.Api/AliasVault.Api.csproj b/src/AliasVault.Api/AliasVault.Api.csproj index a0e0a0f4..42d1f4a9 100644 --- a/src/AliasVault.Api/AliasVault.Api.csproj +++ b/src/AliasVault.Api/AliasVault.Api.csproj @@ -6,6 +6,7 @@ enable AliasVault.Api Linux + True diff --git a/src/AliasVault.Api/Controllers/AliasController.cs b/src/AliasVault.Api/Controllers/AliasController.cs index 6a15a2d5..192f2638 100644 --- a/src/AliasVault.Api/Controllers/AliasController.cs +++ b/src/AliasVault.Api/Controllers/AliasController.cs @@ -1,9 +1,16 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) lanedirt. All rights reserved. +// Licensed under the MIT license. See LICENSE.md file in the project root for full license information. +// +//----------------------------------------------------------------------- + namespace AliasVault.Api.Controllers; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; using AliasDb; using AliasVault.Shared.Models.WebApi; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Identity = AliasVault.Shared.Models.WebApi.Identity; using Service = AliasVault.Shared.Models.WebApi.Service; diff --git a/src/AliasVault.Api/Controllers/AuthController.cs b/src/AliasVault.Api/Controllers/AuthController.cs index 08f14ba8..0aee9721 100644 --- a/src/AliasVault.Api/Controllers/AuthController.cs +++ b/src/AliasVault.Api/Controllers/AuthController.cs @@ -1,16 +1,25 @@ -using System.Security.Cryptography; -using AliasDb; -using AliasVault.Shared.Models; +//----------------------------------------------------------------------- +// +// Copyright (c) lanedirt. All rights reserved. +// Licensed under the MIT license. See LICENSE.md file in the project root for full license information. +// +//----------------------------------------------------------------------- namespace AliasVault.Api.Controllers; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; +using System.Security.Cryptography; using System.Text; +using AliasDb; +using AliasVault.Shared.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.IdentityModel.Tokens; +/// +/// Auth controller for handling authentication. +/// [Route("api/[controller]")] [ApiController] public class AuthController : ControllerBase @@ -19,9 +28,14 @@ public class AuthController : ControllerBase private readonly UserManager _userManager; private readonly SignInManager _signInManager; private readonly IConfiguration _configuration; - private const string LoginProvider = "AliasVault"; - private const string RefreshToken = "RefreshToken"; + /// + /// Initializes a new instance of the class. + /// + /// AliasDbContext instance. + /// UserManager instance. + /// SignInManager instance. + /// IConfiguration instance. public AuthController(AliasDbContext context, UserManager userManager, SignInManager signInManager, IConfiguration configuration) { _context = context; @@ -30,6 +44,11 @@ public AuthController(AliasDbContext context, UserManager userMana _configuration = configuration; } + /// + /// Login endpoint used to process login attempt using credentials. + /// + /// Login model. + /// IActionResult. [HttpPost("login")] public async Task Login([FromBody] LoginModel model) { @@ -39,9 +58,15 @@ public async Task Login([FromBody] LoginModel model) var tokenModel = await GenerateNewTokenForUser(user); return Ok(tokenModel); } + return Unauthorized(); } + /// + /// Refresh endpoint used to refresh an expired access token using a valid refresh token. + /// + /// Token model. + /// IActionResult. [HttpPost("refresh")] public async Task Refresh([FromBody] TokenModel tokenModel) { @@ -73,13 +98,13 @@ public async Task Refresh([FromBody] TokenModel tokenModel) var newRefreshToken = GenerateRefreshToken(); // Add new refresh token. - _context.AspNetUserRefreshTokens.Add(new AspNetUserRefreshToken + await _context.AspNetUserRefreshTokens.AddAsync(new AspNetUserRefreshToken { UserId = user.Id, DeviceIdentifier = deviceIdentifier, Value = newRefreshToken, ExpireDate = DateTime.Now.AddDays(30), - CreatedAt = DateTime.Now + CreatedAt = DateTime.Now, }); await _context.SaveChangesAsync(); @@ -88,6 +113,11 @@ public async Task Refresh([FromBody] TokenModel tokenModel) } + /// + /// Revoke endpoint used to revoke a refresh token. + /// + /// Token model. + /// IActionResult. [HttpPost("revoke")] public async Task Revoke([FromBody] TokenModel model) { @@ -97,7 +127,7 @@ public async Task Revoke([FromBody] TokenModel model) return Unauthorized("User not found (email-1)"); } - var user = await _userManager.FindByIdAsync(principal.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? ""); + var user = await _userManager.FindByIdAsync(principal.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty); if (user == null) { return Unauthorized("User not found (email-2)"); @@ -118,6 +148,11 @@ public async Task Revoke([FromBody] TokenModel model) return Ok("Refresh token revoked successfully"); } + /// + /// Register endpoint used to register a new user. + /// + /// Register model. + /// IActionResult. [HttpPost("register")] public async Task Register([FromBody] RegisterModel model) { @@ -146,7 +181,7 @@ private string GenerateJwtToken(IdentityUser user) new Claim(ClaimTypes.NameIdentifier, user.Id), new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.Email, user.Email), - new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) + new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])); @@ -181,7 +216,7 @@ private ClaimsPrincipal GetPrincipalFromExpiredToken(string token) ValidateIssuer = false, ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"])), - ValidateLifetime = false + ValidateLifetime = false, }; var tokenHandler = new JwtSecurityTokenHandler(); @@ -219,13 +254,13 @@ private async Task GenerateNewTokenForUser(IdentityUser user) _context.AspNetUserRefreshTokens.RemoveRange(existingTokens); // Add new refresh token. - _context.AspNetUserRefreshTokens.Add(new AspNetUserRefreshToken + await _context.AspNetUserRefreshTokens.AddAsync(new AspNetUserRefreshToken { UserId = user.Id, DeviceIdentifier = deviceIdentifier, Value = refreshToken, ExpireDate = DateTime.Now.AddDays(30), - CreatedAt = DateTime.Now + CreatedAt = DateTime.Now, }); await _context.SaveChangesAsync(); diff --git a/src/AliasVault.Api/Controllers/AuthenticatedRequestController.cs b/src/AliasVault.Api/Controllers/AuthenticatedRequestController.cs index 59f84c02..d9bff929 100644 --- a/src/AliasVault.Api/Controllers/AuthenticatedRequestController.cs +++ b/src/AliasVault.Api/Controllers/AuthenticatedRequestController.cs @@ -1,10 +1,15 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) lanedirt. All rights reserved. +// Licensed under the MIT license. See LICENSE.md file in the project root for full license information. +// +//----------------------------------------------------------------------- +using System.Security.Claims; using Microsoft.AspNetCore.Authorization; - -namespace AliasVault.Api.Controllers; - using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; -using System.Security.Claims; + +namespace AliasVault.Api.Controllers; [Route("api/[controller]")] [ApiController] diff --git a/src/AliasVault.Api/Controllers/IdentityController.cs b/src/AliasVault.Api/Controllers/IdentityController.cs index 05db825a..bb244ff3 100644 --- a/src/AliasVault.Api/Controllers/IdentityController.cs +++ b/src/AliasVault.Api/Controllers/IdentityController.cs @@ -1,13 +1,25 @@ -using AliasGenerators.Identity; -using AliasGenerators.Identity.Implementations; - +//----------------------------------------------------------------------- +// +// Copyright (c) lanedirt. All rights reserved. +// Licensed under the MIT license. See LICENSE.md file in the project root for full license information. +// +//----------------------------------------------------------------------- namespace AliasVault.Api.Controllers; +using AliasGenerators.Identity; +using AliasGenerators.Identity.Implementations; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +/// +/// Controller for identity generation. +/// public class IdentityController : AuthenticatedRequestController { + /// + /// Initializes a new instance of the class. + /// + /// UserManager instance. public IdentityController(UserManager userManager) : base(userManager) { } diff --git a/src/AliasVault.Api/Program.cs b/src/AliasVault.Api/Program.cs index 4da4ef7e..6119af47 100644 --- a/src/AliasVault.Api/Program.cs +++ b/src/AliasVault.Api/Program.cs @@ -1,3 +1,10 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) lanedirt. All rights reserved. +// Licensed under the MIT license. See LICENSE.md file in the project root for full license information. +// +//----------------------------------------------------------------------- + using System.Data.Common; using System.Text; using AliasDb; @@ -14,9 +21,9 @@ builder.Services.AddLogging(logging => { logging.AddConsole(); - logging.SetMinimumLevel(LogLevel.Debug); // Set the minimum level to Information - logging.AddFilter("Microsoft.AspNetCore.Identity.DataProtectorTokenProvider", LogLevel.Debug); // Ensure Identity logs are captured - logging.AddFilter("Microsoft.AspNetCore.Identity.UserManager", LogLevel.Debug); // Ensure Identity logs are captured + logging.SetMinimumLevel(LogLevel.Error); + logging.AddFilter("Microsoft.AspNetCore.Identity.DataProtectorTokenProvider", LogLevel.Error); + logging.AddFilter("Microsoft.AspNetCore.Identity.UserManager", LogLevel.Error); }); // Add services to the container. @@ -42,7 +49,7 @@ builder.Services.AddDataProtection(); builder.Services.Configure(options => { - options.TokenLifespan = TimeSpan.FromDays(30); // Set token lifespan for refresh tokens + options.TokenLifespan = TimeSpan.FromDays(30); options.Name = "AliasVault"; }); builder.Services.AddIdentity(options => @@ -57,8 +64,6 @@ options.Tokens.ProviderMap.Add("AliasVault", new TokenProviderDescriptor(typeof(DataProtectorTokenProvider))); }) .AddEntityFrameworkStores() - // Note: The AliasVault token provider is used to generate refresh tokens and is also defined - // in the AuthController. .AddDefaultTokenProviders() .AddTokenProvider>("AliasVault"); @@ -86,7 +91,8 @@ // Configure CORS builder.Services.AddCors(options => { - options.AddPolicy("CorsPolicy", + options.AddPolicy( + "CorsPolicy", policy => policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader()); @@ -106,20 +112,22 @@ Name = "Authorization", Type = SecuritySchemeType.Http, BearerFormat = "JWT", - Scheme = "Bearer" + Scheme = "Bearer", }); - c.AddSecurityRequirement(new OpenApiSecurityRequirement { + c.AddSecurityRequirement(new OpenApiSecurityRequirement { - new OpenApiSecurityScheme { - Reference = new OpenApiReference + new OpenApiSecurityScheme { - Type = ReferenceType.SecurityScheme, - Id = "Bearer" - } + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer", + }, + }, + Array.Empty() }, - Array.Empty() - }}); + }); }); var app = builder.Build(); @@ -144,23 +152,10 @@ var container = scope.ServiceProvider; var db = container.GetRequiredService(); - db.Database.EnsureCreated(); - - /*if (!db..Any()) - { - try - { - db.Initialize(); - } - catch (Exception ex) - { - var logger = container.GetRequiredService>(); - logger.LogError(ex, "An error occurred seeding the database. Error: {Message}", ex.Message); - } - }*/ + await db.Database.EnsureCreatedAsync(); } -app.Run(); +await app.RunAsync(); /// /// For starting the WebAPI project in-memory from E2ETests project.