Code style refactor

This commit is contained in:
Leendert de Borst
2024-06-11 21:54:18 +02:00
parent 638e8a4ccb
commit d34b1ec68e
10 changed files with 118 additions and 58 deletions

View File

@@ -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]

View File

@@ -6,8 +6,8 @@
//-----------------------------------------------------------------------
namespace AliasDb;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
/// <summary>
/// The AliasDbContext class.

View File

@@ -6,9 +6,9 @@
//-----------------------------------------------------------------------
namespace AliasDb;
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
/// <summary>
/// Refresh tokens for users.

View File

@@ -6,9 +6,9 @@
//-----------------------------------------------------------------------
namespace AliasDb;
using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Identity;
/// <summary>
/// Login object.

View File

@@ -6,6 +6,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>AliasVault.Api</RootNamespace>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>

View File

@@ -1,9 +1,16 @@
//-----------------------------------------------------------------------
// <copyright file="AliasController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
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;

View File

@@ -1,16 +1,25 @@
using System.Security.Cryptography;
using AliasDb;
using AliasVault.Shared.Models;
//-----------------------------------------------------------------------
// <copyright file="AuthController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.Api.Controllers;
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;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
/// <summary>
/// Auth controller for handling authentication.
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
@@ -19,9 +28,14 @@ public class AuthController : ControllerBase
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
private readonly IConfiguration _configuration;
private const string LoginProvider = "AliasVault";
private const string RefreshToken = "RefreshToken";
/// <summary>
/// Initializes a new instance of the <see cref="AuthController"/> class.
/// </summary>
/// <param name="context">AliasDbContext instance.</param>
/// <param name="userManager">UserManager instance.</param>
/// <param name="signInManager">SignInManager instance.</param>
/// <param name="configuration">IConfiguration instance.</param>
public AuthController(AliasDbContext context, UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, IConfiguration configuration)
{
_context = context;
@@ -30,6 +44,11 @@ public class AuthController : ControllerBase
_configuration = configuration;
}
/// <summary>
/// Login endpoint used to process login attempt using credentials.
/// </summary>
/// <param name="model">Login model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
@@ -39,9 +58,15 @@ public class AuthController : ControllerBase
var tokenModel = await GenerateNewTokenForUser(user);
return Ok(tokenModel);
}
return Unauthorized();
}
/// <summary>
/// Refresh endpoint used to refresh an expired access token using a valid refresh token.
/// </summary>
/// <param name="tokenModel">Token model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("refresh")]
public async Task<IActionResult> Refresh([FromBody] TokenModel tokenModel)
{
@@ -73,13 +98,13 @@ public class AuthController : ControllerBase
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 class AuthController : ControllerBase
}
/// <summary>
/// Revoke endpoint used to revoke a refresh token.
/// </summary>
/// <param name="model">Token model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("revoke")]
public async Task<IActionResult> Revoke([FromBody] TokenModel model)
{
@@ -97,7 +127,7 @@ public class AuthController : ControllerBase
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 class AuthController : ControllerBase
return Ok("Refresh token revoked successfully");
}
/// <summary>
/// Register endpoint used to register a new user.
/// </summary>
/// <param name="model">Register model.</param>
/// <returns>IActionResult.</returns>
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegisterModel model)
{
@@ -146,7 +181,7 @@ public class AuthController : ControllerBase
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 @@ public class AuthController : ControllerBase
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 @@ public class AuthController : ControllerBase
_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();

View File

@@ -1,10 +1,15 @@
//-----------------------------------------------------------------------
// <copyright file="AuthenticatedRequestController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
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]

View File

@@ -1,13 +1,25 @@
using AliasGenerators.Identity;
using AliasGenerators.Identity.Implementations;
//-----------------------------------------------------------------------
// <copyright file="IdentityController.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
namespace AliasVault.Api.Controllers;
using AliasGenerators.Identity;
using AliasGenerators.Identity.Implementations;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
/// <summary>
/// Controller for identity generation.
/// </summary>
public class IdentityController : AuthenticatedRequestController
{
/// <summary>
/// Initializes a new instance of the <see cref="IdentityController"/> class.
/// </summary>
/// <param name="userManager">UserManager instance.</param>
public IdentityController(UserManager<IdentityUser> userManager) : base(userManager)
{
}

View File

@@ -1,3 +1,10 @@
//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="lanedirt">
// Copyright (c) lanedirt. All rights reserved.
// Licensed under the MIT license. See LICENSE.md file in the project root for full license information.
// </copyright>
//-----------------------------------------------------------------------
using System.Data.Common;
using System.Text;
using AliasDb;
@@ -14,9 +21,9 @@ var configuration = builder.Configuration;
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.AddDbContext<AliasDbContext>((container, options) =>
builder.Services.AddDataProtection();
builder.Services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(30); // Set token lifespan for refresh tokens
options.TokenLifespan = TimeSpan.FromDays(30);
options.Name = "AliasVault";
});
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
@@ -57,8 +64,6 @@ builder.Services.AddIdentity<IdentityUser, IdentityRole>(options =>
options.Tokens.ProviderMap.Add("AliasVault", new TokenProviderDescriptor(typeof(DataProtectorTokenProvider<IdentityUser>)));
})
.AddEntityFrameworkStores<AliasDbContext>()
// Note: The AliasVault token provider is used to generate refresh tokens and is also defined
// in the AuthController.
.AddDefaultTokenProviders()
.AddTokenProvider<DataProtectorTokenProvider<IdentityUser>>("AliasVault");
@@ -86,7 +91,8 @@ builder.Services.AddAuthentication(options =>
// Configure CORS
builder.Services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
options.AddPolicy(
"CorsPolicy",
policy => policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
@@ -106,20 +112,22 @@ builder.Services.AddSwaggerGen(c =>
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<string>()
},
Array.Empty<string>()
}});
});
});
var app = builder.Build();
@@ -144,23 +152,10 @@ using (var scope = app.Services.CreateScope())
var container = scope.ServiceProvider;
var db = container.GetRequiredService<AliasDbContext>();
db.Database.EnsureCreated();
/*if (!db..Any())
{
try
{
db.Initialize();
}
catch (Exception ex)
{
var logger = container.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the database. Error: {Message}", ex.Message);
}
}*/
await db.Database.EnsureCreatedAsync();
}
app.Run();
await app.RunAsync();
/// <summary>
/// For starting the WebAPI project in-memory from E2ETests project.