Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Build and run unit tests

env:
DOTNET_VERSION: '9.x'
DOTNET_VERSION: '10.x'

on:
push:
Expand All @@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Set up .NET Core
uses: actions/setup-dotnet@v5
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Release CI/CD
env:
AZURE_WEBAPP_NAME: app-open5etools
AZURE_WEBAPP_PACKAGE_PATH: '.'
DOTNET_VERSION: '9.x'
DOTNET_VERSION: '10.x'

on:
push:
Expand All @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6

- name: Set up .NET Core
uses: actions/setup-dotnet@v5
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
<Nullable>enable</Nullable>
Expand Down
25 changes: 12 additions & 13 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@
<PackageVersion Include="LigerShark.WebOptimizer.Core" Version="3.0.477" />
<PackageVersion Include="Mapster" Version="7.4.0" />
<PackageVersion Include="Mapster.DependencyInjection" Version="1.0.1" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.10" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SQLite" Version="9.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.10" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.10" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="9.0.10" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SQLite" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Microsoft.Web.LibraryManager.Build" Version="3.0.71" />
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
<PackageVersion Include="Serilog.Settings.Configuration" Version="9.0.0" />
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageVersion Include="Serilog.Sinks.MSSqlServer" Version="9.0.1" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
<PackageVersion Include="System.Text.Json" Version="9.0.10" />
<PackageVersion Include="Serilog.Sinks.MSSqlServer" Version="9.0.2" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="xunit.v3" Version="3.1.0" />
<PackageVersion Include="xunit.v3" Version="3.2.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<PackageVersion Include="coverlet.collector" Version="6.0.4" />
<PackageVersion Include="X.PagedList" Version="10.5.9" />
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This repo is for playing around with DnD5E SRD materials, trying out some techno

## Prerequisites

You have .NET 9 SDK installed.
You have .NET 10 SDK installed.

## Get the code

Expand Down
7 changes: 4 additions & 3 deletions src/Open5ETools.Core/Common/Exceptions/ServiceException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@

public class ServiceException : Exception
{
public const string GeneralError = "GeneralError";
public const string GeneralAggregateError = "GeneralAggregateError";
public const string EntityNotFoundException = "EntityNotFoundException";
public const string RequiredValidation = "RequiredValidation";
public const string EncounterNotPossible = "EncounterNotPossible";

public object[]? Args { get; }

public string? Field { get; }
public string Field { get; }

public ServiceException(string message, params object[] args) : base(message)
{
Field = null;
Field = string.Empty;
Args = args;
}

Expand All @@ -26,7 +27,7 @@ public ServiceException(string message, string field, params object[] args) : ba
public ServiceException(string message, Exception innerException, params object[] args) : base(message,
innerException)
{
Field = null;
Field = string.Empty;
Args = args;
}

Expand Down
27 changes: 15 additions & 12 deletions src/Open5ETools.Core/Common/Helpers/PasswordHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,34 @@ namespace Open5ETools.Core.Common.Helpers;

public static class PasswordHelper
{
private const int Iterations = 10000;
private const int HashLength = 20;
private const int SaltLength = 16;
private static readonly HashAlgorithmName HashAlgorithmName = HashAlgorithmName.SHA512;

public static string EncryptPassword(string password)
{
using var randomNumberGenerator = RandomNumberGenerator.Create();
var salt = new byte[16];
var salt = new byte[SaltLength];
randomNumberGenerator.GetBytes(salt);
using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA512);
var hash = pbkdf2.GetBytes(20);
var hashBytes = new byte[36];
Array.Copy(salt, 0, hashBytes, 0, 16);
Array.Copy(hash, 0, hashBytes, 16, 20);
var hash = Rfc2898DeriveBytes.Pbkdf2(password, salt, Iterations, HashAlgorithmName, HashLength);
var hashBytes = new byte[SaltLength + HashLength];
Array.Copy(salt, 0, hashBytes, 0, SaltLength);
Array.Copy(hash, 0, hashBytes, SaltLength, HashLength);
return Convert.ToBase64String(hashBytes);
}

public static bool CheckPassword(string savedPasswordHash, string password)
{
var result = true;
var hashBytes = Convert.FromBase64String(savedPasswordHash);
var salt = new byte[16];
Array.Copy(hashBytes, 0, salt, 0, 16);
using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA512);
var hash = pbkdf2.GetBytes(20);
var salt = new byte[SaltLength];
Array.Copy(hashBytes, 0, salt, 0, SaltLength);
var hash = Rfc2898DeriveBytes.Pbkdf2(password, salt, Iterations, HashAlgorithmName, HashLength);

for (var i = 0; i < 20; i++)
for (var i = 0; i < HashLength; i++)
{
if (hashBytes[i + 16] == hash[i])
if (hashBytes[i + SaltLength] == hash[i])
continue;
result = false;
break;
Expand Down
1 change: 0 additions & 1 deletion src/Open5ETools.Core/Open5ETools.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<PackageReference Include="Mapster"/>
<PackageReference Include="Mapster.DependencyInjection"/>
<PackageReference Include="Microsoft.EntityFrameworkCore"/>
<PackageReference Include="System.Text.Json"/>
<PackageReference Include="Serilog.AspNetCore"/>
<PackageReference Include="Serilog.Settings.Configuration"/>
<PackageReference Include="Serilog.Sinks.File"/>
Expand Down
9 changes: 5 additions & 4 deletions src/Open5ETools.Web/Controllers/Web/DungeonController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Text.Json;
using Open5ETools.Core.Common.Exceptions;
using Open5ETools.Resources;
using Open5ETools.Web.Extensions;

namespace Open5ETools.Web.Controllers.Web;

Expand Down Expand Up @@ -70,7 +71,7 @@ public async Task<IActionResult> Delete(int id, CancellationToken cancellationTo
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting dungeon.");
this.HandleException(ex, _logger, "Error deleting dungeon.");
}

return RedirectToAction(nameof(Index));
Expand Down Expand Up @@ -109,7 +110,7 @@ await _dungeonService.RenameDungeonAsync(model.Id, model.UserId, model.NewDungeo
}
catch (Exception ex)
{
_logger.LogError(ex, "Error renaming dungeon.");
this.HandleException(ex, _logger, "Error renaming dungeon.");
}

return View(model);
Expand All @@ -125,7 +126,7 @@ public async Task<IActionResult> DeleteOption(int id, CancellationToken cancella
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting dungeon option.");
this.HandleException(ex, _logger, "Error deleting dungeon option.");
}

return RedirectToAction(nameof(Index));
Expand Down Expand Up @@ -168,7 +169,7 @@ public async Task<IActionResult> Create(DungeonOptionCreateViewModel model, Canc
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating dungeon.");
this.HandleException(ex, _logger, "Error creating dungeon.");
}
}

Expand Down
11 changes: 7 additions & 4 deletions src/Open5ETools.Web/Controllers/Web/ProfileController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
using Microsoft.AspNetCore.Mvc;
using Open5ETools.Core.Common.Interfaces.Services;
using Open5ETools.Core.Common.Models.Services;
using Open5ETools.Web.Extensions;
using Open5ETools.Web.Models.Profile;

namespace Open5ETools.Web.Controllers.Web;

[Authorize]
public class ProfileController(IUserService userService,
public class ProfileController(
IUserService userService,
ICurrentUserService currentUserService,
IMapper mapper,
ILogger<ProfileController> logger) : Controller
Expand All @@ -34,7 +36,8 @@ public IActionResult ChangePassword()

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangePassword(ProfileChangePasswordModel model, CancellationToken cancellationToken)
public async Task<IActionResult> ChangePassword(ProfileChangePasswordModel model,
CancellationToken cancellationToken)
{
if (ModelState.IsValid)
{
Expand All @@ -45,10 +48,10 @@ public async Task<IActionResult> ChangePassword(ProfileChangePasswordModel model
}
catch (Exception ex)
{
_logger.LogError(ex, "Error changing password.");
ModelState.AddModelError("", ex.Message);
this.HandleException(ex, _logger, "Error changing password.");
}
}

return View(model);
}
}
15 changes: 9 additions & 6 deletions src/Open5ETools.Web/Controllers/Web/UserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Open5ETools.Core.Common.Interfaces.Services;
using Open5ETools.Core.Common.Models.Services;
using Open5ETools.Core.Domain;
using Open5ETools.Web.Extensions;
using Open5ETools.Web.Models.User;

namespace Open5ETools.Web.Controllers.Web;
Expand Down Expand Up @@ -44,10 +45,10 @@ public async Task<IActionResult> Create(UserCreateViewModel model, CancellationT
}
catch (Exception ex)
{
_logger.LogError(ex, "Error creating user.");
ModelState.AddModelError("", ex.Message);
this.HandleException(ex, _logger, "Error creating user.");
}
}

return View(model);
}

Expand All @@ -73,10 +74,10 @@ public async Task<IActionResult> Edit(UserEditViewModel model, CancellationToken
}
catch (Exception ex)
{
_logger.LogError(ex, "Error editing user.");
ModelState.AddModelError("", ex.Message);
this.HandleException(ex, _logger, "Error editing user.");
}
}

return View(model);
}

Expand All @@ -90,8 +91,9 @@ public async Task<IActionResult> Delete(int id, CancellationToken cancellationTo
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting user.");
this.HandleException(ex, _logger, "Error deleting user.");
}

return RedirectToAction("Index");
}

Expand All @@ -105,8 +107,9 @@ public async Task<IActionResult> Restore(int id, CancellationToken cancellationT
}
catch (Exception ex)
{
_logger.LogError(ex, "Error restoring user.");
this.HandleException(ex, _logger, "Error restoring user.");
}

return RedirectToAction("Index");
}
}
4 changes: 2 additions & 2 deletions src/Open5ETools.Web/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /app
COPY . ./

RUN dotnet restore ./src/Open5ETools.Web/Open5ETools.Web.csproj
RUN dotnet publish "src/Open5ETools.Web/Open5ETools.Web.csproj" -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:9.0
FROM mcr.microsoft.com/dotnet/aspnet:10.0
WORKDIR /app
COPY --from=build /app/out ./

Expand Down
33 changes: 33 additions & 0 deletions src/Open5ETools.Web/Extensions/ControllerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Open5ETools.Core.Common.Exceptions;

namespace Open5ETools.Web.Extensions;

public static class ControllerExtensions
{
public static void HandleException(this Controller controller, Exception ex, ILogger logger,
string? defaultError = null)
{
switch (ex)
{
case ServiceAggregateException ae:
{
foreach (var exception in ae.GetInnerExceptions())
{
controller.ModelState.AddModelError(exception.Field, exception.Message);
}

break;
}
case ServiceException e:
controller.ModelState.AddModelError(e.Field, e.Message);
break;
default:
logger.LogError(ex, "{GetDisplayUrl}: {DefaultError}", controller.Request.GetDisplayUrl(),
defaultError ?? ServiceException.GeneralError);
controller.ModelState.AddModelError(string.Empty, defaultError ?? ServiceException.GeneralError);
break;
}
}
}
2 changes: 1 addition & 1 deletion src/Open5ETools.Web/Open5ETools.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<TieredCompilation>true</TieredCompilation>
<PreserveCompilationReferences>true</PreserveCompilationReferences>
<AssemblyVersion>1.0.3.2</AssemblyVersion>
<AssemblyVersion>1.0.4.0</AssemblyVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityModel"/>
Expand Down