chore(backend): add roslynator and fix diagnostics

This commit is contained in:
sam 2024-12-08 15:17:18 +01:00
parent 649988db25
commit f8e6032449
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
20 changed files with 60 additions and 38 deletions

View file

@ -45,5 +45,8 @@ resharper_wrap_chained_binary_patterns = chop_if_long
resharper_wrap_list_pattern = chop_always resharper_wrap_list_pattern = chop_always
resharper_wrap_object_and_collection_initializer_style = chop_always resharper_wrap_object_and_collection_initializer_style = chop_always
# Roslynator properties
dotnet_diagnostic.RCS1194.severity = none
[*generated.cs] [*generated.cs]
generated_code = true generated_code = true

View file

@ -38,7 +38,7 @@ public class AuthController(
if (config.DiscordAuth is { ClientId: not null, ClientSecret: not null }) if (config.DiscordAuth is { ClientId: not null, ClientSecret: not null })
{ {
discord = discord =
$"https://discord.com/oauth2/authorize?response_type=code" "https://discord.com/oauth2/authorize?response_type=code"
+ $"&client_id={config.DiscordAuth.ClientId}&scope=identify" + $"&client_id={config.DiscordAuth.ClientId}&scope=identify"
+ $"&prompt=none&state={state}" + $"&prompt=none&state={state}"
+ $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}"; + $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}";

View file

@ -104,7 +104,7 @@ public class DiscordAuthController(
); );
string url = 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" + $"&client_id={config.DiscordAuth.ClientId}&scope=identify"
+ $"&prompt=none&state={state}" + $"&prompt=none&state={state}"
+ $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}"; + $"&redirect_uri={HttpUtility.UrlEncode($"{config.BaseUrl}/auth/callback/discord")}";

View file

@ -48,7 +48,9 @@ public class EmailAuthController(
ct ct
) )
) )
{
return NoContent(); return NoContent();
}
mailService.QueueAccountCreationEmail(req.Email, state); mailService.QueueAccountCreationEmail(req.Email, state);
return NoContent(); return NoContent();

View file

@ -124,7 +124,9 @@ public class FlagsController(
} }
} }
else else
{
_logger.Debug("Flag file {Hash} is used by other flags, not deleting", hash); _logger.Debug("Flag file {Hash} is used by other flags, not deleting", hash);
}
await tx.CommitAsync(); await tx.CommitAsync();

View file

@ -93,12 +93,14 @@ public partial class InternalController(DatabaseContext db) : ControllerBase
HttpMethodAttribute? httpMethodAttribute = HttpMethodAttribute? httpMethodAttribute =
endpoint.Metadata.GetMetadata<HttpMethodAttribute>(); endpoint.Metadata.GetMetadata<HttpMethodAttribute>();
if ( if (
httpMethodAttribute != null httpMethodAttribute?.HttpMethods.Any(x =>
&& !httpMethodAttribute.HttpMethods.Any(x =>
x.Equals(requestMethod, StringComparison.OrdinalIgnoreCase) x.Equals(requestMethod, StringComparison.OrdinalIgnoreCase)
) ) == false
) )
{
continue; continue;
}
return endpoint; return endpoint;
} }

View file

@ -238,7 +238,7 @@ public class MembersController(
throw new ApiError.BadRequest( throw new ApiError.BadRequest(
"A member with that name already exists", "A member with that name already exists",
"name", "name",
req.Name! req.Name
); );
} }

View file

@ -135,7 +135,9 @@ public class UsersController(
else else
{ {
if (TimeZoneInfo.TryFindSystemTimeZoneById(req.Timezone, out _)) if (TimeZoneInfo.TryFindSystemTimeZoneById(req.Timezone, out _))
{
user.Timezone = req.Timezone; user.Timezone = req.Timezone;
}
else else
{ {
errors.Add( errors.Add(
@ -174,7 +176,7 @@ public class UsersController(
throw new ApiError.BadRequest( throw new ApiError.BadRequest(
"That username is already taken.", "That username is already taken.",
"username", "username",
req.Username! req.Username
); );
} }

View file

@ -44,18 +44,18 @@ public class DatabaseContext(DbContextOptions options) : DbContext(options)
.UseSnakeCaseNamingConvention() .UseSnakeCaseNamingConvention()
.UseExceptionProcessor(); .UseExceptionProcessor();
public DbSet<User> Users { get; init; } public DbSet<User> Users { get; init; } = null!;
public DbSet<Member> Members { get; init; } public DbSet<Member> Members { get; init; } = null!;
public DbSet<AuthMethod> AuthMethods { get; init; } public DbSet<AuthMethod> AuthMethods { get; init; } = null!;
public DbSet<FediverseApplication> FediverseApplications { get; init; } public DbSet<FediverseApplication> FediverseApplications { get; init; } = null!;
public DbSet<Token> Tokens { get; init; } public DbSet<Token> Tokens { get; init; } = null!;
public DbSet<Application> Applications { get; init; } public DbSet<Application> Applications { get; init; } = null!;
public DbSet<TemporaryKey> TemporaryKeys { get; init; } public DbSet<TemporaryKey> TemporaryKeys { get; init; } = null!;
public DbSet<DataExport> DataExports { get; init; } public DbSet<DataExport> DataExports { get; init; } = null!;
public DbSet<PrideFlag> PrideFlags { get; init; } public DbSet<PrideFlag> PrideFlags { get; init; } = null!;
public DbSet<UserFlag> UserFlags { get; init; } public DbSet<UserFlag> UserFlags { get; init; } = null!;
public DbSet<MemberFlag> MemberFlags { get; init; } public DbSet<MemberFlag> MemberFlags { get; init; } = null!;
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{ {

View file

@ -24,10 +24,7 @@ namespace Foxnouns.Backend.Database.Migrations
client_secret = table.Column<string>(type: "text", nullable: false), client_secret = table.Column<string>(type: "text", nullable: false),
instance_type = table.Column<int>(type: "integer", nullable: false), instance_type = table.Column<int>(type: "integer", nullable: false),
}, },
constraints: table => constraints: table => table.PrimaryKey("pk_fediverse_applications", x => x.id)
{
table.PrimaryKey("pk_fediverse_applications", x => x.id);
}
); );
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
@ -46,10 +43,7 @@ namespace Foxnouns.Backend.Database.Migrations
names = table.Column<string>(type: "jsonb", nullable: false), names = table.Column<string>(type: "jsonb", nullable: false),
pronouns = table.Column<string>(type: "jsonb", nullable: false), pronouns = table.Column<string>(type: "jsonb", nullable: false),
}, },
constraints: table => constraints: table => table.PrimaryKey("pk_users", x => x.id)
{
table.PrimaryKey("pk_users", x => x.id);
}
); );
migrationBuilder.CreateTable( migrationBuilder.CreateTable(

View file

@ -26,7 +26,7 @@ namespace Foxnouns.Backend.Database.Migrations
table: "tokens", table: "tokens",
type: "bytea", type: "bytea",
nullable: false, nullable: false,
defaultValue: new byte[0] defaultValue: Array.Empty<byte>()
); );
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
@ -40,10 +40,7 @@ namespace Foxnouns.Backend.Database.Migrations
scopes = table.Column<string[]>(type: "text[]", nullable: false), scopes = table.Column<string[]>(type: "text[]", nullable: false),
redirect_uris = table.Column<string[]>(type: "text[]", nullable: false), redirect_uris = table.Column<string[]>(type: "text[]", nullable: false),
}, },
constraints: table => constraints: table => table.PrimaryKey("pk_applications", x => x.id)
{
table.PrimaryKey("pk_applications", x => x.id);
}
); );
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(

View file

@ -32,10 +32,7 @@ namespace Foxnouns.Backend.Database.Migrations
nullable: false nullable: false
), ),
}, },
constraints: table => constraints: table => table.PrimaryKey("pk_temporary_keys", x => x.id)
{
table.PrimaryKey("pk_temporary_keys", x => x.id);
}
); );
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(

View file

@ -30,6 +30,10 @@
<PackageReference Include="Npgsql.Json.NET" Version="8.0.3"/> <PackageReference Include="Npgsql.Json.NET" Version="8.0.3"/>
<PackageReference Include="prometheus-net" Version="8.2.1"/> <PackageReference Include="prometheus-net" Version="8.2.1"/>
<PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1"/> <PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1"/>
<PackageReference Include="Roslynator.Analyzers" Version="4.12.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Sentry.AspNetCore" Version="4.9.0"/> <PackageReference Include="Sentry.AspNetCore" Version="4.9.0"/>
<PackageReference Include="Serilog" Version="4.0.1"/> <PackageReference Include="Serilog" Version="4.0.1"/>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1"/> <PackageReference Include="Serilog.AspNetCore" Version="8.0.1"/>

View file

@ -57,7 +57,7 @@ public class CreateDataExportInvocable(
_logger.Information("Generating data export for user {UserId}", user.Id); _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); using var zip = new ZipArchive(stream, ZipArchiveMode.Create, true);
zip.Comment = zip.Comment =
$"This archive for {user.Username} ({user.Id}) was generated at {InstantPattern.General.Format(clock.GetCurrentInstant())}"; $"This archive for {user.Username} ({user.Id}) was generated at {InstantPattern.General.Format(clock.GetCurrentInstant())}";

View file

@ -44,7 +44,9 @@ public class AuthorizationMiddleware : IMiddleware
&& token.User.Role != UserRole.Admin && token.User.Role != UserRole.Admin
&& token.User.Role != UserRole.Moderator && token.User.Role != UserRole.Moderator
) )
{
throw new ApiError.Forbidden("This endpoint can only be used by moderators."); throw new ApiError.Forbidden("This endpoint can only be used by moderators.");
}
await next(ctx); await next(ctx);
} }

View file

@ -142,6 +142,8 @@ public class RemoteAuthService(
|| accountState.UserId != userId || accountState.UserId != userId
|| (instance != null && accountState.Instance != instance) || (instance != null && accountState.Instance != instance)
) )
{
throw new ApiError.BadRequest("Invalid state", "state", state); throw new ApiError.BadRequest("Invalid state", "state", state);
}
} }
} }

View file

@ -74,7 +74,9 @@ public class UserRendererService(
user.Timezone != null user.Timezone != null
&& TimeZoneInfo.TryFindSystemTimeZoneById(user.Timezone, out TimeZoneInfo? tz) && TimeZoneInfo.TryFindSystemTimeZoneById(user.Timezone, out TimeZoneInfo? tz)
) )
{
utcOffset = (int)tz.GetUtcOffset(DateTimeOffset.UtcNow).TotalSeconds; utcOffset = (int)tz.GetUtcOffset(DateTimeOffset.UtcNow).TotalSeconds;
}
return new UserResponse( return new UserResponse(
user.Id, user.Id,

View file

@ -5,10 +5,11 @@ using Newtonsoft.Json.Serialization;
namespace Foxnouns.Backend.Utils; namespace Foxnouns.Backend.Utils;
/// <summary> /// <summary>
/// A base class used for PATCH requests which stores information on whether a key is explicitly set to null or not passed at all. /// <para>A base class used for PATCH requests which stores information on whether a key is explicitly set to null or not passed at all.</para>
/// /// <para>
/// HasProperty() should not be used for properties that cannot be set to null--a null value should be treated /// 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. /// as an unset value in those cases.
/// </para>
/// </summary> /// </summary>
public abstract class PatchRequest public abstract class PatchRequest
{ {

View file

@ -63,7 +63,10 @@ public static partial class ValidationUtils
string.Equals(u, username, StringComparison.InvariantCultureIgnoreCase) string.Equals(u, username, StringComparison.InvariantCultureIgnoreCase)
) )
) )
{
return ValidationError.GenericValidationError("Username is not allowed", username); return ValidationError.GenericValidationError("Username is not allowed", username);
}
return null; return null;
} }
@ -89,7 +92,10 @@ public static partial class ValidationUtils
string.Equals(u, memberName, StringComparison.InvariantCultureIgnoreCase) string.Equals(u, memberName, StringComparison.InvariantCultureIgnoreCase)
) )
) )
{
return ValidationError.GenericValidationError("Name is not allowed", memberName); return ValidationError.GenericValidationError("Name is not allowed", memberName);
}
return null; return null;
} }

View file

@ -194,6 +194,12 @@
"prometheus-net": "8.2.1" "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": { "Sentry.AspNetCore": {
"type": "Direct", "type": "Direct",
"requested": "[4.9.0, )", "requested": "[4.9.0, )",