diff --git a/Foxnouns.Backend/Controllers/UsersController.cs b/Foxnouns.Backend/Controllers/UsersController.cs index a2c6219..78967f3 100644 --- a/Foxnouns.Backend/Controllers/UsersController.cs +++ b/Foxnouns.Backend/Controllers/UsersController.cs @@ -20,16 +20,15 @@ public class UsersController( { [HttpGet("{userRef}")] [ProducesResponseType(statusCode: StatusCodes.Status200OK)] - public async Task GetUserAsync(string userRef, CancellationToken ct = default) + public async Task GetUserAsync(string userRef) { - var user = await db.ResolveUserAsync(userRef, CurrentToken, ct); + var user = await db.ResolveUserAsync(userRef, CurrentToken); return Ok(await userRendererService.RenderUserAsync( user, selfUser: CurrentUser, token: CurrentToken, renderMembers: true, - renderAuthMethods: true, - ct: ct + renderAuthMethods: true )); } @@ -60,11 +59,6 @@ public class UsersController( user.Bio = req.Bio; } - if (req.HasProperty(nameof(req.Links))) - { - user.Links = req.Links ?? []; - } - if (req.HasProperty(nameof(req.Avatar))) errors.Add(("avatar", ValidationUtils.ValidateAvatar(req.Avatar))); @@ -156,37 +150,5 @@ public class UsersController( public string? DisplayName { get; init; } public string? Bio { get; init; } public string? Avatar { get; init; } - public string[]? Links { get; init; } - } - - - [HttpGet("@me/settings")] - [Authorize("user.read_hidden")] - [ProducesResponseType(statusCode: StatusCodes.Status200OK)] - public async Task GetUserSettingsAsync(CancellationToken ct = default) - { - var user = await db.Users.FirstAsync(u => u.Id == CurrentUser!.Id, ct); - return Ok(user.Settings); - } - - [HttpPatch("@me/settings")] - [Authorize("user.read_hidden", "user.update")] - [ProducesResponseType(statusCode: StatusCodes.Status200OK)] - public async Task UpdateUserSettingsAsync([FromBody] UpdateUserSettingsRequest req, CancellationToken ct = default) - { - var user = await db.Users.FirstAsync(u => u.Id == CurrentUser!.Id, ct); - - if (req.HasProperty(nameof(req.DarkMode))) - user.Settings.DarkMode = req.DarkMode; - - db.Update(user); - await db.SaveChangesAsync(ct); - - return Ok(user.Settings); - } - - public class UpdateUserSettingsRequest : PatchRequest - { - public bool? DarkMode { get; init; } } } \ No newline at end of file diff --git a/Foxnouns.Backend/Database/DatabaseContext.cs b/Foxnouns.Backend/Database/DatabaseContext.cs index 26087b8..725afb6 100644 --- a/Foxnouns.Backend/Database/DatabaseContext.cs +++ b/Foxnouns.Backend/Database/DatabaseContext.cs @@ -63,7 +63,6 @@ public class DatabaseContext : DbContext modelBuilder.Entity().Property(u => u.Names).HasColumnType("jsonb"); modelBuilder.Entity().Property(u => u.Pronouns).HasColumnType("jsonb"); modelBuilder.Entity().Property(u => u.CustomPreferences).HasColumnType("jsonb"); - modelBuilder.Entity().Property(u => u.Settings).HasColumnType("jsonb"); modelBuilder.Entity().Property(m => m.Fields).HasColumnType("jsonb"); modelBuilder.Entity().Property(m => m.Names).HasColumnType("jsonb"); diff --git a/Foxnouns.Backend/Database/DatabaseQueryExtensions.cs b/Foxnouns.Backend/Database/DatabaseQueryExtensions.cs index b6ccaaa..1d4e851 100644 --- a/Foxnouns.Backend/Database/DatabaseQueryExtensions.cs +++ b/Foxnouns.Backend/Database/DatabaseQueryExtensions.cs @@ -9,29 +9,23 @@ namespace Foxnouns.Backend.Database; public static class DatabaseQueryExtensions { - public static async Task ResolveUserAsync(this DatabaseContext context, string userRef, Token? token, - CancellationToken ct = default) + public static async Task ResolveUserAsync(this DatabaseContext context, string userRef, Token? token) { - if (userRef == "@me") - { - return token != null - ? await context.Users.FirstAsync(u => u.Id == token.UserId, ct) - : throw new ApiError.Unauthorized("This endpoint requires an authenticated user.", - ErrorCode.AuthenticationRequired); - } + if (userRef == "@me" && token != null) + return await context.Users.FirstAsync(u => u.Id == token.UserId); User? user; if (Snowflake.TryParse(userRef, out var snowflake)) { user = await context.Users .Where(u => !u.Deleted) - .FirstOrDefaultAsync(u => u.Id == snowflake, ct); + .FirstOrDefaultAsync(u => u.Id == snowflake); if (user != null) return user; } user = await context.Users .Where(u => !u.Deleted) - .FirstOrDefaultAsync(u => u.Username == userRef, ct); + .FirstOrDefaultAsync(u => u.Username == userRef); if (user != null) return user; throw new ApiError.NotFound("No user with that ID or username found.", code: ErrorCode.UserNotFound); } diff --git a/Foxnouns.Backend/Database/Migrations/20240905191709_AddUserSettings.Designer.cs b/Foxnouns.Backend/Database/Migrations/20240905191709_AddUserSettings.Designer.cs deleted file mode 100644 index 45b3a53..0000000 --- a/Foxnouns.Backend/Database/Migrations/20240905191709_AddUserSettings.Designer.cs +++ /dev/null @@ -1,432 +0,0 @@ -// -using System; -using System.Collections.Generic; -using Foxnouns.Backend.Database; -using Foxnouns.Backend.Database.Models; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using NodaTime; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Foxnouns.Backend.Database.Migrations -{ - [DbContext(typeof(DatabaseContext))] - [Migration("20240905191709_AddUserSettings")] - partial class AddUserSettings - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Application", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("client_id"); - - b.Property("ClientSecret") - .IsRequired() - .HasColumnType("text") - .HasColumnName("client_secret"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("RedirectUris") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("redirect_uris"); - - b.Property("Scopes") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("scopes"); - - b.HasKey("Id") - .HasName("pk_applications"); - - b.ToTable("applications", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.AuthMethod", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("AuthType") - .HasColumnType("integer") - .HasColumnName("auth_type"); - - b.Property("FediverseApplicationId") - .HasColumnType("bigint") - .HasColumnName("fediverse_application_id"); - - b.Property("RemoteId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("remote_id"); - - b.Property("RemoteUsername") - .HasColumnType("text") - .HasColumnName("remote_username"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_auth_methods"); - - b.HasIndex("FediverseApplicationId") - .HasDatabaseName("ix_auth_methods_fediverse_application_id"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_auth_methods_user_id"); - - b.ToTable("auth_methods", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.FediverseApplication", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("ClientId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("client_id"); - - b.Property("ClientSecret") - .IsRequired() - .HasColumnType("text") - .HasColumnName("client_secret"); - - b.Property("Domain") - .IsRequired() - .HasColumnType("text") - .HasColumnName("domain"); - - b.Property("InstanceType") - .HasColumnType("integer") - .HasColumnName("instance_type"); - - b.HasKey("Id") - .HasName("pk_fediverse_applications"); - - b.ToTable("fediverse_applications", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Member", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("Avatar") - .HasColumnType("text") - .HasColumnName("avatar"); - - b.Property("Bio") - .HasColumnType("text") - .HasColumnName("bio"); - - b.Property("DisplayName") - .HasColumnType("text") - .HasColumnName("display_name"); - - b.Property>("Fields") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("fields"); - - b.Property("Links") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("links"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property>("Names") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("names"); - - b.Property>("Pronouns") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("pronouns"); - - b.Property("Unlisted") - .HasColumnType("boolean") - .HasColumnName("unlisted"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_members"); - - b.HasIndex("UserId", "Name") - .IsUnique() - .HasDatabaseName("ix_members_user_id_name"); - - b.ToTable("members", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.TemporaryKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Expires") - .HasColumnType("timestamp with time zone") - .HasColumnName("expires"); - - b.Property("Key") - .IsRequired() - .HasColumnType("text") - .HasColumnName("key"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasColumnName("value"); - - b.HasKey("Id") - .HasName("pk_temporary_keys"); - - b.HasIndex("Key") - .IsUnique() - .HasDatabaseName("ix_temporary_keys_key"); - - b.ToTable("temporary_keys", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Token", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("ApplicationId") - .HasColumnType("bigint") - .HasColumnName("application_id"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("expires_at"); - - b.Property("Hash") - .IsRequired() - .HasColumnType("bytea") - .HasColumnName("hash"); - - b.Property("ManuallyExpired") - .HasColumnType("boolean") - .HasColumnName("manually_expired"); - - b.Property("Scopes") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("scopes"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_tokens"); - - b.HasIndex("ApplicationId") - .HasDatabaseName("ix_tokens_application_id"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_tokens_user_id"); - - b.ToTable("tokens", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("Avatar") - .HasColumnType("text") - .HasColumnName("avatar"); - - b.Property("Bio") - .HasColumnType("text") - .HasColumnName("bio"); - - b.Property>("CustomPreferences") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("custom_preferences"); - - b.Property("Deleted") - .HasColumnType("boolean") - .HasColumnName("deleted"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("deleted_at"); - - b.Property("DeletedBy") - .HasColumnType("bigint") - .HasColumnName("deleted_by"); - - b.Property("DisplayName") - .HasColumnType("text") - .HasColumnName("display_name"); - - b.Property>("Fields") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("fields"); - - b.Property("LastActive") - .HasColumnType("timestamp with time zone") - .HasColumnName("last_active"); - - b.Property("Links") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("links"); - - b.Property("ListHidden") - .HasColumnType("boolean") - .HasColumnName("list_hidden"); - - b.Property("MemberTitle") - .HasColumnType("text") - .HasColumnName("member_title"); - - b.Property>("Names") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("names"); - - b.Property("Password") - .HasColumnType("text") - .HasColumnName("password"); - - b.Property>("Pronouns") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("pronouns"); - - b.Property("Role") - .HasColumnType("integer") - .HasColumnName("role"); - - b.Property("Settings") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("settings"); - - b.Property("Username") - .IsRequired() - .HasColumnType("text") - .HasColumnName("username"); - - b.HasKey("Id") - .HasName("pk_users"); - - b.HasIndex("Username") - .IsUnique() - .HasDatabaseName("ix_users_username"); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.AuthMethod", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.FediverseApplication", "FediverseApplication") - .WithMany() - .HasForeignKey("FediverseApplicationId") - .HasConstraintName("fk_auth_methods_fediverse_applications_fediverse_application_id"); - - b.HasOne("Foxnouns.Backend.Database.Models.User", "User") - .WithMany("AuthMethods") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_auth_methods_users_user_id"); - - b.Navigation("FediverseApplication"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Member", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", "User") - .WithMany("Members") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_members_users_user_id"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Token", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.Application", "Application") - .WithMany() - .HasForeignKey("ApplicationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_tokens_applications_application_id"); - - b.HasOne("Foxnouns.Backend.Database.Models.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_tokens_users_user_id"); - - b.Navigation("Application"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b => - { - b.Navigation("AuthMethods"); - - b.Navigation("Members"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Foxnouns.Backend/Database/Migrations/20240905191709_AddUserSettings.cs b/Foxnouns.Backend/Database/Migrations/20240905191709_AddUserSettings.cs deleted file mode 100644 index 49c5bd1..0000000 --- a/Foxnouns.Backend/Database/Migrations/20240905191709_AddUserSettings.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Foxnouns.Backend.Database.Models; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Foxnouns.Backend.Database.Migrations -{ - /// - public partial class AddUserSettings : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "settings", - table: "users", - type: "jsonb", - nullable: false, - defaultValueSql: "'{}'"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "settings", - table: "users"); - } - } -} diff --git a/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs b/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs index 36ca955..fc99285 100644 --- a/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs +++ b/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs @@ -150,11 +150,6 @@ namespace Foxnouns.Backend.Database.Migrations .HasColumnType("text") .HasColumnName("display_name"); - b.Property>("Fields") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("fields"); - b.Property("Links") .IsRequired() .HasColumnType("text[]") @@ -165,16 +160,6 @@ namespace Foxnouns.Backend.Database.Migrations .HasColumnType("text") .HasColumnName("name"); - b.Property>("Names") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("names"); - - b.Property>("Pronouns") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("pronouns"); - b.Property("Unlisted") .HasColumnType("boolean") .HasColumnName("unlisted"); @@ -284,7 +269,7 @@ namespace Foxnouns.Backend.Database.Migrations .HasColumnType("text") .HasColumnName("bio"); - b.Property>("CustomPreferences") + b.Property>("CustomPreferences") .IsRequired() .HasColumnType("jsonb") .HasColumnName("custom_preferences"); @@ -305,11 +290,6 @@ namespace Foxnouns.Backend.Database.Migrations .HasColumnType("text") .HasColumnName("display_name"); - b.Property>("Fields") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("fields"); - b.Property("LastActive") .HasColumnType("timestamp with time zone") .HasColumnName("last_active"); @@ -327,29 +307,14 @@ namespace Foxnouns.Backend.Database.Migrations .HasColumnType("text") .HasColumnName("member_title"); - b.Property>("Names") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("names"); - b.Property("Password") .HasColumnType("text") .HasColumnName("password"); - b.Property>("Pronouns") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("pronouns"); - b.Property("Role") .HasColumnType("integer") .HasColumnName("role"); - b.Property("Settings") - .IsRequired() - .HasColumnType("jsonb") - .HasColumnName("settings"); - b.Property("Username") .IsRequired() .HasColumnType("text") @@ -393,6 +358,72 @@ namespace Foxnouns.Backend.Database.Migrations .IsRequired() .HasConstraintName("fk_members_users_user_id"); + b.OwnsOne("System.Collections.Generic.List", "Fields", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("MemberId"); + + b1.ToTable("members"); + + b1.ToJson("fields"); + + b1.WithOwner() + .HasForeignKey("MemberId") + .HasConstraintName("fk_members_members_id"); + }); + + b.OwnsOne("System.Collections.Generic.List", "Names", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("MemberId"); + + b1.ToTable("members"); + + b1.ToJson("names"); + + b1.WithOwner() + .HasForeignKey("MemberId") + .HasConstraintName("fk_members_members_id"); + }); + + b.OwnsOne("System.Collections.Generic.List", "Pronouns", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("MemberId"); + + b1.ToTable("members"); + + b1.ToJson("pronouns"); + + b1.WithOwner() + .HasForeignKey("MemberId") + .HasConstraintName("fk_members_members_id"); + }); + + b.Navigation("Fields") + .IsRequired(); + + b.Navigation("Names") + .IsRequired(); + + b.Navigation("Pronouns") + .IsRequired(); + b.Navigation("User"); }); @@ -417,6 +448,78 @@ namespace Foxnouns.Backend.Database.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b => + { + b.OwnsOne("Foxnouns.Backend.Database.Models.User.Fields#List", "Fields", b1 => + { + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("UserId") + .HasName("pk_users"); + + b1.ToTable("users"); + + b1.ToJson("fields"); + + b1.WithOwner() + .HasForeignKey("UserId") + .HasConstraintName("fk_users_users_user_id"); + }); + + b.OwnsOne("Foxnouns.Backend.Database.Models.User.Names#List", "Names", b1 => + { + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("UserId") + .HasName("pk_users"); + + b1.ToTable("users"); + + b1.ToJson("names"); + + b1.WithOwner() + .HasForeignKey("UserId") + .HasConstraintName("fk_users_users_user_id"); + }); + + b.OwnsOne("Foxnouns.Backend.Database.Models.User.Pronouns#List", "Pronouns", b1 => + { + b1.Property("UserId") + .HasColumnType("bigint"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("UserId") + .HasName("pk_users"); + + b1.ToTable("users"); + + b1.ToJson("pronouns"); + + b1.WithOwner() + .HasForeignKey("UserId") + .HasConstraintName("fk_users_users_user_id"); + }); + + b.Navigation("Fields") + .IsRequired(); + + b.Navigation("Names") + .IsRequired(); + + b.Navigation("Pronouns") + .IsRequired(); + }); + modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b => { b.Navigation("AuthMethods"); diff --git a/Foxnouns.Backend/Database/Models/User.cs b/Foxnouns.Backend/Database/Models/User.cs index de48944..c152e65 100644 --- a/Foxnouns.Backend/Database/Models/User.cs +++ b/Foxnouns.Backend/Database/Models/User.cs @@ -25,7 +25,6 @@ public class User : BaseModel public List Members { get; } = []; public List AuthMethods { get; } = []; - public UserSettings Settings { get; set; } = new(); public required Instant LastActive { get; set; } @@ -59,9 +58,4 @@ public enum PreferenceSize Large, Normal, Small, -} - -public class UserSettings -{ - public bool? DarkMode { get; set; } = null; } \ No newline at end of file diff --git a/Foxnouns.Backend/ExpectedError.cs b/Foxnouns.Backend/ExpectedError.cs index f277265..6e39af7 100644 --- a/Foxnouns.Backend/ExpectedError.cs +++ b/Foxnouns.Backend/ExpectedError.cs @@ -23,15 +23,11 @@ public class ApiError(string message, HttpStatusCode? statusCode = null, ErrorCo public readonly HttpStatusCode StatusCode = statusCode ?? HttpStatusCode.InternalServerError; public readonly ErrorCode ErrorCode = errorCode ?? ErrorCode.InternalServerError; - public class Unauthorized(string message, ErrorCode errorCode = ErrorCode.AuthenticationError) : ApiError(message, - statusCode: HttpStatusCode.Unauthorized, - errorCode: errorCode); + public class Unauthorized(string message) : ApiError(message, statusCode: HttpStatusCode.Unauthorized, + errorCode: ErrorCode.AuthenticationError); - public class Forbidden( - string message, - IEnumerable? scopes = null, - ErrorCode errorCode = ErrorCode.Forbidden) - : ApiError(message, statusCode: HttpStatusCode.Forbidden, errorCode: errorCode) + public class Forbidden(string message, IEnumerable? scopes = null) + : ApiError(message, statusCode: HttpStatusCode.Forbidden) { public readonly string[] Scopes = scopes?.ToArray() ?? []; } @@ -119,8 +115,6 @@ public enum ErrorCode Forbidden, BadRequest, AuthenticationError, - AuthenticationRequired, - MissingScopes, GenericApiError, UserNotFound, MemberNotFound, diff --git a/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs b/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs index 6d4bc49..dd0d97f 100644 --- a/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs +++ b/Foxnouns.Backend/Middleware/AuthorizationMiddleware.cs @@ -18,10 +18,10 @@ public class AuthorizationMiddleware : IMiddleware var token = ctx.GetToken(); if (token == null) - throw new ApiError.Unauthorized("This endpoint requires an authenticated user.", ErrorCode.AuthenticationRequired); + throw new ApiError.Unauthorized("This endpoint requires an authenticated user."); if (attribute.Scopes.Length > 0 && attribute.Scopes.Except(token.Scopes.ExpandScopes()).Any()) throw new ApiError.Forbidden("This endpoint requires ungranted scopes.", - attribute.Scopes.Except(token.Scopes.ExpandScopes()), ErrorCode.MissingScopes); + attribute.Scopes.Except(token.Scopes.ExpandScopes())); if (attribute.RequireAdmin && token.User.Role != UserRole.Admin) throw new ApiError.Forbidden("This endpoint can only be used by admins."); if (attribute.RequireModerator && token.User.Role != UserRole.Admin && token.User.Role != UserRole.Moderator) diff --git a/Foxnouns.Backend/Services/UserRendererService.cs b/Foxnouns.Backend/Services/UserRendererService.cs index 4449488..9bb198e 100644 --- a/Foxnouns.Backend/Services/UserRendererService.cs +++ b/Foxnouns.Backend/Services/UserRendererService.cs @@ -12,8 +12,7 @@ public class UserRendererService(DatabaseContext db, MemberRendererService membe public async Task RenderUserAsync(User user, User? selfUser = null, Token? token = null, bool renderMembers = true, - bool renderAuthMethods = false, - CancellationToken ct = default) + bool renderAuthMethods = false) { var isSelfUser = selfUser?.Id == user.Id; var tokenCanReadHiddenMembers = token.HasScope("member.read") && isSelfUser; @@ -25,7 +24,7 @@ public class UserRendererService(DatabaseContext db, MemberRendererService membe renderAuthMethods = renderAuthMethods && tokenPrivileged; IEnumerable members = - renderMembers ? await db.Members.Where(m => m.UserId == user.Id).ToListAsync(ct) : []; + renderMembers ? await db.Members.Where(m => m.UserId == user.Id).ToListAsync() : []; // Unless the user is requesting their own members AND the token can read hidden members, we filter out unlisted members. if (!(isSelfUser && tokenCanReadHiddenMembers)) members = members.Where(m => m.Unlisted); @@ -33,7 +32,7 @@ public class UserRendererService(DatabaseContext db, MemberRendererService membe ? await db.AuthMethods .Where(a => a.UserId == user.Id) .Include(a => a.FediverseApplication) - .ToListAsync(ct) + .ToListAsync() : []; return new UserResponse(