From f8e60324491e4983a8fe9d7bb4a49025cc7b3719 Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 8 Dec 2024 15:17:18 +0100 Subject: [PATCH] chore(backend): add roslynator and fix diagnostics --- .editorconfig | 3 +++ .../Authentication/AuthController.cs | 2 +- .../Authentication/DiscordAuthController.cs | 2 +- .../Authentication/EmailAuthController.cs | 2 ++ .../Controllers/FlagsController.cs | 2 ++ .../Controllers/InternalController.cs | 8 ++++--- .../Controllers/MembersController.cs | 2 +- .../Controllers/UsersController.cs | 4 +++- Foxnouns.Backend/Database/DatabaseContext.cs | 22 +++++++++---------- .../Migrations/20240527132444_Init.cs | 10 ++------- .../20240528125310_AddApplications.cs | 7 ++---- .../20240611225328_AddTemporaryKeyCache.cs | 5 +---- Foxnouns.Backend/Foxnouns.Backend.csproj | 4 ++++ .../Jobs/CreateDataExportInvocable.cs | 2 +- .../Middleware/AuthorizationMiddleware.cs | 2 ++ .../Services/Auth/RemoteAuthService.cs | 2 ++ .../Services/UserRendererService.cs | 2 ++ Foxnouns.Backend/Utils/PatchRequest.cs | 5 +++-- .../Utils/ValidationUtils.Strings.cs | 6 +++++ Foxnouns.Backend/packages.lock.json | 6 +++++ 20 files changed, 60 insertions(+), 38 deletions(-) diff --git a/.editorconfig b/.editorconfig index af4c22d..e6b41f9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -45,5 +45,8 @@ resharper_wrap_chained_binary_patterns = chop_if_long resharper_wrap_list_pattern = chop_always resharper_wrap_object_and_collection_initializer_style = chop_always +# Roslynator properties +dotnet_diagnostic.RCS1194.severity = none + [*generated.cs] generated_code = true \ No newline at end of file diff --git a/Foxnouns.Backend/Controllers/Authentication/AuthController.cs b/Foxnouns.Backend/Controllers/Authentication/AuthController.cs index 84c4902..ced8c3d 100644 --- a/Foxnouns.Backend/Controllers/Authentication/AuthController.cs +++ b/Foxnouns.Backend/Controllers/Authentication/AuthController.cs @@ -38,7 +38,7 @@ public class AuthController( if (config.DiscordAuth is { ClientId: not null, ClientSecret: not null }) { discord = - $"https://discord.com/oauth2/authorize?response_type=code" + "https://discord.com/oauth2/authorize?response_type=code" + $"&client_id={config.DiscordAuth.ClientId}&scope=identify" + $"&prompt=none&state={state}" + $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}"; diff --git a/Foxnouns.Backend/Controllers/Authentication/DiscordAuthController.cs b/Foxnouns.Backend/Controllers/Authentication/DiscordAuthController.cs index c3af765..f7f9c3d 100644 --- a/Foxnouns.Backend/Controllers/Authentication/DiscordAuthController.cs +++ b/Foxnouns.Backend/Controllers/Authentication/DiscordAuthController.cs @@ -104,7 +104,7 @@ public class DiscordAuthController( ); string url = - $"https://discord.com/oauth2/authorize?response_type=code" + "https://discord.com/oauth2/authorize?response_type=code" + $"&client_id={config.DiscordAuth.ClientId}&scope=identify" + $"&prompt=none&state={state}" + $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}"; diff --git a/Foxnouns.Backend/Controllers/Authentication/EmailAuthController.cs b/Foxnouns.Backend/Controllers/Authentication/EmailAuthController.cs index 3884fec..4162f4c 100644 --- a/Foxnouns.Backend/Controllers/Authentication/EmailAuthController.cs +++ b/Foxnouns.Backend/Controllers/Authentication/EmailAuthController.cs @@ -48,7 +48,9 @@ public class EmailAuthController( ct ) ) + { return NoContent(); + } mailService.QueueAccountCreationEmail(req.Email, state); return NoContent(); diff --git a/Foxnouns.Backend/Controllers/FlagsController.cs b/Foxnouns.Backend/Controllers/FlagsController.cs index 92d87b4..9bb9f91 100644 --- a/Foxnouns.Backend/Controllers/FlagsController.cs +++ b/Foxnouns.Backend/Controllers/FlagsController.cs @@ -124,7 +124,9 @@ public class FlagsController( } } else + { _logger.Debug("Flag file {Hash} is used by other flags, not deleting", hash); + } await tx.CommitAsync(); diff --git a/Foxnouns.Backend/Controllers/InternalController.cs b/Foxnouns.Backend/Controllers/InternalController.cs index a3fdaf9..9e94022 100644 --- a/Foxnouns.Backend/Controllers/InternalController.cs +++ b/Foxnouns.Backend/Controllers/InternalController.cs @@ -93,12 +93,14 @@ public partial class InternalController(DatabaseContext db) : ControllerBase HttpMethodAttribute? httpMethodAttribute = endpoint.Metadata.GetMetadata(); if ( - httpMethodAttribute != null - && !httpMethodAttribute.HttpMethods.Any(x => + httpMethodAttribute?.HttpMethods.Any(x => x.Equals(requestMethod, StringComparison.OrdinalIgnoreCase) - ) + ) == false ) + { continue; + } + return endpoint; } diff --git a/Foxnouns.Backend/Controllers/MembersController.cs b/Foxnouns.Backend/Controllers/MembersController.cs index 445da13..a9021b9 100644 --- a/Foxnouns.Backend/Controllers/MembersController.cs +++ b/Foxnouns.Backend/Controllers/MembersController.cs @@ -238,7 +238,7 @@ public class MembersController( throw new ApiError.BadRequest( "A member with that name already exists", "name", - req.Name! + req.Name ); } diff --git a/Foxnouns.Backend/Controllers/UsersController.cs b/Foxnouns.Backend/Controllers/UsersController.cs index 46e1398..98d5645 100644 --- a/Foxnouns.Backend/Controllers/UsersController.cs +++ b/Foxnouns.Backend/Controllers/UsersController.cs @@ -135,7 +135,9 @@ public class UsersController( else { if (TimeZoneInfo.TryFindSystemTimeZoneById(req.Timezone, out _)) + { user.Timezone = req.Timezone; + } else { errors.Add( @@ -174,7 +176,7 @@ public class UsersController( throw new ApiError.BadRequest( "That username is already taken.", "username", - req.Username! + req.Username ); } diff --git a/Foxnouns.Backend/Database/DatabaseContext.cs b/Foxnouns.Backend/Database/DatabaseContext.cs index deffec7..f79f4fe 100644 --- a/Foxnouns.Backend/Database/DatabaseContext.cs +++ b/Foxnouns.Backend/Database/DatabaseContext.cs @@ -44,18 +44,18 @@ public class DatabaseContext(DbContextOptions options) : DbContext(options) .UseSnakeCaseNamingConvention() .UseExceptionProcessor(); - public DbSet Users { get; init; } - public DbSet Members { get; init; } - public DbSet AuthMethods { get; init; } - public DbSet FediverseApplications { get; init; } - public DbSet Tokens { get; init; } - public DbSet Applications { get; init; } - public DbSet TemporaryKeys { get; init; } - public DbSet DataExports { get; init; } + public DbSet Users { get; init; } = null!; + public DbSet Members { get; init; } = null!; + public DbSet AuthMethods { get; init; } = null!; + public DbSet FediverseApplications { get; init; } = null!; + public DbSet Tokens { get; init; } = null!; + public DbSet Applications { get; init; } = null!; + public DbSet TemporaryKeys { get; init; } = null!; + public DbSet DataExports { get; init; } = null!; - public DbSet PrideFlags { get; init; } - public DbSet UserFlags { get; init; } - public DbSet MemberFlags { get; init; } + public DbSet PrideFlags { get; init; } = null!; + public DbSet UserFlags { get; init; } = null!; + public DbSet MemberFlags { get; init; } = null!; protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { diff --git a/Foxnouns.Backend/Database/Migrations/20240527132444_Init.cs b/Foxnouns.Backend/Database/Migrations/20240527132444_Init.cs index 7a29aa0..7d2f05c 100644 --- a/Foxnouns.Backend/Database/Migrations/20240527132444_Init.cs +++ b/Foxnouns.Backend/Database/Migrations/20240527132444_Init.cs @@ -24,10 +24,7 @@ namespace Foxnouns.Backend.Database.Migrations client_secret = table.Column(type: "text", nullable: false), instance_type = table.Column(type: "integer", nullable: false), }, - constraints: table => - { - table.PrimaryKey("pk_fediverse_applications", x => x.id); - } + constraints: table => table.PrimaryKey("pk_fediverse_applications", x => x.id) ); migrationBuilder.CreateTable( @@ -46,10 +43,7 @@ namespace Foxnouns.Backend.Database.Migrations names = table.Column(type: "jsonb", nullable: false), pronouns = table.Column(type: "jsonb", nullable: false), }, - constraints: table => - { - table.PrimaryKey("pk_users", x => x.id); - } + constraints: table => table.PrimaryKey("pk_users", x => x.id) ); migrationBuilder.CreateTable( diff --git a/Foxnouns.Backend/Database/Migrations/20240528125310_AddApplications.cs b/Foxnouns.Backend/Database/Migrations/20240528125310_AddApplications.cs index 366fba3..4fced78 100644 --- a/Foxnouns.Backend/Database/Migrations/20240528125310_AddApplications.cs +++ b/Foxnouns.Backend/Database/Migrations/20240528125310_AddApplications.cs @@ -26,7 +26,7 @@ namespace Foxnouns.Backend.Database.Migrations table: "tokens", type: "bytea", nullable: false, - defaultValue: new byte[0] + defaultValue: Array.Empty() ); migrationBuilder.CreateTable( @@ -40,10 +40,7 @@ namespace Foxnouns.Backend.Database.Migrations scopes = table.Column(type: "text[]", nullable: false), redirect_uris = table.Column(type: "text[]", nullable: false), }, - constraints: table => - { - table.PrimaryKey("pk_applications", x => x.id); - } + constraints: table => table.PrimaryKey("pk_applications", x => x.id) ); migrationBuilder.CreateIndex( diff --git a/Foxnouns.Backend/Database/Migrations/20240611225328_AddTemporaryKeyCache.cs b/Foxnouns.Backend/Database/Migrations/20240611225328_AddTemporaryKeyCache.cs index 7d131da..931e8ab 100644 --- a/Foxnouns.Backend/Database/Migrations/20240611225328_AddTemporaryKeyCache.cs +++ b/Foxnouns.Backend/Database/Migrations/20240611225328_AddTemporaryKeyCache.cs @@ -32,10 +32,7 @@ namespace Foxnouns.Backend.Database.Migrations nullable: false ), }, - constraints: table => - { - table.PrimaryKey("pk_temporary_keys", x => x.id); - } + constraints: table => table.PrimaryKey("pk_temporary_keys", x => x.id) ); migrationBuilder.CreateIndex( diff --git a/Foxnouns.Backend/Foxnouns.Backend.csproj b/Foxnouns.Backend/Foxnouns.Backend.csproj index d604012..794f2b9 100644 --- a/Foxnouns.Backend/Foxnouns.Backend.csproj +++ b/Foxnouns.Backend/Foxnouns.Backend.csproj @@ -30,6 +30,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Foxnouns.Backend/Jobs/CreateDataExportInvocable.cs b/Foxnouns.Backend/Jobs/CreateDataExportInvocable.cs index 8eab65e..8e34d01 100644 --- a/Foxnouns.Backend/Jobs/CreateDataExportInvocable.cs +++ b/Foxnouns.Backend/Jobs/CreateDataExportInvocable.cs @@ -57,7 +57,7 @@ public class CreateDataExportInvocable( _logger.Information("Generating data export for user {UserId}", user.Id); - using var stream = new MemoryStream(); + await using var stream = new MemoryStream(); using var zip = new ZipArchive(stream, ZipArchiveMode.Create, true); zip.Comment = $"This archive for {user.Username} ({user.Id}) was generated at {InstantPattern.General.Format(clock.GetCurrentInstant())}"; diff --git a/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs b/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs index 78fd485..114e870 100644 --- a/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs +++ b/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs @@ -44,7 +44,9 @@ public class AuthorizationMiddleware : IMiddleware && token.User.Role != UserRole.Admin && token.User.Role != UserRole.Moderator ) + { throw new ApiError.Forbidden("This endpoint can only be used by moderators."); + } await next(ctx); } diff --git a/Foxnouns.Backend/Services/Auth/RemoteAuthService.cs b/Foxnouns.Backend/Services/Auth/RemoteAuthService.cs index 2dd4234..c3ca685 100644 --- a/Foxnouns.Backend/Services/Auth/RemoteAuthService.cs +++ b/Foxnouns.Backend/Services/Auth/RemoteAuthService.cs @@ -142,6 +142,8 @@ public class RemoteAuthService( || accountState.UserId != userId || (instance != null && accountState.Instance != instance) ) + { throw new ApiError.BadRequest("Invalid state", "state", state); + } } } diff --git a/Foxnouns.Backend/Services/UserRendererService.cs b/Foxnouns.Backend/Services/UserRendererService.cs index cc77ee9..9f6da8b 100644 --- a/Foxnouns.Backend/Services/UserRendererService.cs +++ b/Foxnouns.Backend/Services/UserRendererService.cs @@ -74,7 +74,9 @@ public class UserRendererService( user.Timezone != null && TimeZoneInfo.TryFindSystemTimeZoneById(user.Timezone, out TimeZoneInfo? tz) ) + { utcOffset = (int)tz.GetUtcOffset(DateTimeOffset.UtcNow).TotalSeconds; + } return new UserResponse( user.Id, diff --git a/Foxnouns.Backend/Utils/PatchRequest.cs b/Foxnouns.Backend/Utils/PatchRequest.cs index 10e4177..025eeae 100644 --- a/Foxnouns.Backend/Utils/PatchRequest.cs +++ b/Foxnouns.Backend/Utils/PatchRequest.cs @@ -5,10 +5,11 @@ using Newtonsoft.Json.Serialization; namespace Foxnouns.Backend.Utils; /// -/// A base class used for PATCH requests which stores information on whether a key is explicitly set to null or not passed at all. -/// +/// A base class used for PATCH requests which stores information on whether a key is explicitly set to null or not passed at all. +/// /// HasProperty() should not be used for properties that cannot be set to null--a null value should be treated /// as an unset value in those cases. +/// /// public abstract class PatchRequest { diff --git a/Foxnouns.Backend/Utils/ValidationUtils.Strings.cs b/Foxnouns.Backend/Utils/ValidationUtils.Strings.cs index 53629fd..4d5b444 100644 --- a/Foxnouns.Backend/Utils/ValidationUtils.Strings.cs +++ b/Foxnouns.Backend/Utils/ValidationUtils.Strings.cs @@ -63,7 +63,10 @@ public static partial class ValidationUtils string.Equals(u, username, StringComparison.InvariantCultureIgnoreCase) ) ) + { return ValidationError.GenericValidationError("Username is not allowed", username); + } + return null; } @@ -89,7 +92,10 @@ public static partial class ValidationUtils string.Equals(u, memberName, StringComparison.InvariantCultureIgnoreCase) ) ) + { return ValidationError.GenericValidationError("Name is not allowed", memberName); + } + return null; } diff --git a/Foxnouns.Backend/packages.lock.json b/Foxnouns.Backend/packages.lock.json index 5a5a32b..901341c 100644 --- a/Foxnouns.Backend/packages.lock.json +++ b/Foxnouns.Backend/packages.lock.json @@ -194,6 +194,12 @@ "prometheus-net": "8.2.1" } }, + "Roslynator.Analyzers": { + "type": "Direct", + "requested": "[4.12.9, )", + "resolved": "4.12.9", + "contentHash": "X6lDpN/D5wuinq37KIx+l3GSUe9No+8bCjGBTI5sEEtxapLztkHg6gzNVhMXpXw8P+/5gFYxTXJ5Pf8O4iNz/w==" + }, "Sentry.AspNetCore": { "type": "Direct", "requested": "[4.9.0, )",