diff --git a/.editorconfig b/.editorconfig index 22061dc..e6b41f9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,7 @@ resharper_not_accessed_positional_property_local_highlighting = none # Microsoft .NET properties csharp_new_line_before_members_in_object_initializers = false -csharp_preferred_modifier_order = public, internal, protected, private, file, new, virtual, override, required, abstract, sealed, static, extern, unsafe, volatile, async, readonly:suggestion +csharp_preferred_modifier_order = public, internal, protected, private, file, new, required, abstract, virtual, sealed, static, override, extern, unsafe, volatile, async, readonly:suggestion # ReSharper properties resharper_align_multiline_binary_expressions_chain = false diff --git a/Foxnouns.Backend/Controllers/MetaController.cs b/Foxnouns.Backend/Controllers/MetaController.cs index 0166e86..1f00a7a 100644 --- a/Foxnouns.Backend/Controllers/MetaController.cs +++ b/Foxnouns.Backend/Controllers/MetaController.cs @@ -13,23 +13,20 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . using System.Text.RegularExpressions; -using Foxnouns.Backend.Database.Models; using Foxnouns.Backend.Dto; -using Foxnouns.Backend.Services.Caching; using Foxnouns.Backend.Utils; using Microsoft.AspNetCore.Mvc; namespace Foxnouns.Backend.Controllers; [Route("/api/v2/meta")] -public partial class MetaController(Config config, NoticeCacheService noticeCache) - : ApiControllerBase +public partial class MetaController(Config config) : ApiControllerBase { private const string Repository = "https://codeberg.org/pronounscc/pronouns.cc"; [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task GetMeta(CancellationToken ct = default) => + public IActionResult GetMeta() => Ok( new MetaResponse( Repository, @@ -48,14 +45,10 @@ public partial class MetaController(Config config, NoticeCacheService noticeCach ValidationUtils.MaxCustomPreferences, AuthUtils.MaxAuthMethodsPerType, FlagsController.MaxFlagCount - ), - Notice: NoticeResponse(await noticeCache.GetAsync(ct)) + ) ) ); - private static MetaNoticeResponse? NoticeResponse(Notice? notice) => - notice == null ? null : new MetaNoticeResponse(notice.Id, notice.Message); - [HttpGet("page/{page}")] public async Task GetStaticPageAsync(string page, CancellationToken ct = default) { @@ -78,7 +71,7 @@ public partial class MetaController(Config config, NoticeCacheService noticeCach [HttpGet("/api/v2/coffee")] public IActionResult BrewCoffee() => - StatusCode(StatusCodes.Status418ImATeapot, "Sorry, I'm a teapot!"); + Problem("Sorry, I'm a teapot!", statusCode: StatusCodes.Status418ImATeapot); [GeneratedRegex(@"^[a-z\-_]+$")] private static partial Regex PageRegex(); diff --git a/Foxnouns.Backend/Controllers/Moderation/NoticesController.cs b/Foxnouns.Backend/Controllers/Moderation/NoticesController.cs deleted file mode 100644 index 3d2d6bb..0000000 --- a/Foxnouns.Backend/Controllers/Moderation/NoticesController.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Foxnouns.Backend.Database; -using Foxnouns.Backend.Database.Models; -using Foxnouns.Backend.Dto; -using Foxnouns.Backend.Middleware; -using Foxnouns.Backend.Services; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using NodaTime; - -namespace Foxnouns.Backend.Controllers.Moderation; - -[Route("/api/v2/notices")] -[Authorize("user.moderation")] -[Limit(RequireModerator = true)] -public class NoticesController( - DatabaseContext db, - UserRendererService userRenderer, - ISnowflakeGenerator snowflakeGenerator, - IClock clock -) : ApiControllerBase -{ - [HttpGet] - public async Task GetNoticesAsync(CancellationToken ct = default) - { - List notices = await db - .Notices.Include(n => n.Author) - .OrderByDescending(n => n.Id) - .ToListAsync(ct); - return Ok(notices.Select(RenderNotice)); - } - - [HttpPost] - public async Task CreateNoticeAsync(CreateNoticeRequest req) - { - Instant now = clock.GetCurrentInstant(); - if (req.StartTime < now) - { - throw new ApiError.BadRequest( - "Start time cannot be in the past", - "start_time", - req.StartTime - ); - } - - if (req.EndTime < now) - { - throw new ApiError.BadRequest( - "End time cannot be in the past", - "end_time", - req.EndTime - ); - } - - var notice = new Notice - { - Id = snowflakeGenerator.GenerateSnowflake(), - Message = req.Message, - StartTime = req.StartTime ?? clock.GetCurrentInstant(), - EndTime = req.EndTime, - Author = CurrentUser!, - }; - - db.Add(notice); - await db.SaveChangesAsync(); - - return Ok(RenderNotice(notice)); - } - - private NoticeResponse RenderNotice(Notice notice) => - new( - notice.Id, - notice.Message, - notice.StartTime, - notice.EndTime, - userRenderer.RenderPartialUser(notice.Author) - ); -} diff --git a/Foxnouns.Backend/Controllers/UsersController.cs b/Foxnouns.Backend/Controllers/UsersController.cs index ed9a48f..48a42aa 100644 --- a/Foxnouns.Backend/Controllers/UsersController.cs +++ b/Foxnouns.Backend/Controllers/UsersController.cs @@ -46,15 +46,7 @@ public class UsersController( { User user = await db.ResolveUserAsync(userRef, CurrentToken, ct); return Ok( - await userRenderer.RenderUserAsync( - user, - CurrentUser, - CurrentToken, - renderMembers: true, - renderAuthMethods: true, - renderSettings: true, - ct: ct - ) + await userRenderer.RenderUserAsync(user, CurrentUser, CurrentToken, true, true, ct: ct) ); } @@ -269,6 +261,15 @@ public class UsersController( return Ok(user.CustomPreferences); } + [HttpGet("@me/settings")] + [Authorize("user.read_hidden")] + [ProducesResponseType(statusCode: StatusCodes.Status200OK)] + public async Task GetUserSettingsAsync(CancellationToken ct = default) + { + User 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)] @@ -281,8 +282,6 @@ public class UsersController( if (req.HasProperty(nameof(req.DarkMode))) user.Settings.DarkMode = req.DarkMode; - if (req.HasProperty(nameof(req.LastReadNotice))) - user.Settings.LastReadNotice = req.LastReadNotice; user.LastActive = clock.GetCurrentInstant(); db.Update(user); diff --git a/Foxnouns.Backend/Database/DatabaseContext.cs b/Foxnouns.Backend/Database/DatabaseContext.cs index 2bbcbc7..c9120f3 100644 --- a/Foxnouns.Backend/Database/DatabaseContext.cs +++ b/Foxnouns.Backend/Database/DatabaseContext.cs @@ -73,7 +73,6 @@ public class DatabaseContext(DbContextOptions options) : DbContext(options) public DbSet Reports { get; init; } = null!; public DbSet AuditLog { get; init; } = null!; public DbSet Notifications { get; init; } = null!; - public DbSet Notices { get; init; } = null!; protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { diff --git a/Foxnouns.Backend/Database/Migrations/20250329131053_AddNotices.Designer.cs b/Foxnouns.Backend/Database/Migrations/20250329131053_AddNotices.Designer.cs deleted file mode 100644 index d2df141..0000000 --- a/Foxnouns.Backend/Database/Migrations/20250329131053_AddNotices.Designer.cs +++ /dev/null @@ -1,915 +0,0 @@ -// -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("20250329131053_AddNotices")] - partial class AddNotices - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "9.0.2") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "hstore"); - 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.PrimitiveCollection("RedirectUris") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("redirect_uris"); - - b.PrimitiveCollection("Scopes") - .IsRequired() - .HasColumnType("text[]") - .HasColumnName("scopes"); - - b.HasKey("Id") - .HasName("pk_applications"); - - b.ToTable("applications", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.AuditLogEntry", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.PrimitiveCollection("ClearedFields") - .HasColumnType("text[]") - .HasColumnName("cleared_fields"); - - b.Property("ModeratorId") - .HasColumnType("bigint") - .HasColumnName("moderator_id"); - - b.Property("ModeratorUsername") - .IsRequired() - .HasColumnType("text") - .HasColumnName("moderator_username"); - - b.Property("Reason") - .HasColumnType("text") - .HasColumnName("reason"); - - b.Property("ReportId") - .HasColumnType("bigint") - .HasColumnName("report_id"); - - b.Property("TargetMemberId") - .HasColumnType("bigint") - .HasColumnName("target_member_id"); - - b.Property("TargetMemberName") - .HasColumnType("text") - .HasColumnName("target_member_name"); - - b.Property("TargetUserId") - .HasColumnType("bigint") - .HasColumnName("target_user_id"); - - b.Property("TargetUsername") - .HasColumnType("text") - .HasColumnName("target_username"); - - b.Property("Type") - .HasColumnType("integer") - .HasColumnName("type"); - - b.HasKey("Id") - .HasName("pk_audit_log"); - - b.HasIndex("ReportId") - .IsUnique() - .HasDatabaseName("ix_audit_log_report_id"); - - b.ToTable("audit_log", (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.HasIndex("AuthType", "RemoteId") - .IsUnique() - .HasDatabaseName("ix_auth_methods_auth_type_remote_id") - .HasFilter("fediverse_application_id IS NULL"); - - b.HasIndex("AuthType", "RemoteId", "FediverseApplicationId") - .IsUnique() - .HasDatabaseName("ix_auth_methods_auth_type_remote_id_fediverse_application_id") - .HasFilter("fediverse_application_id IS NOT NULL"); - - b.ToTable("auth_methods", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.DataExport", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("Filename") - .IsRequired() - .HasColumnType("text") - .HasColumnName("filename"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_data_exports"); - - b.HasIndex("Filename") - .IsUnique() - .HasDatabaseName("ix_data_exports_filename"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_data_exports_user_id"); - - b.ToTable("data_exports", (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("ForceRefresh") - .HasColumnType("boolean") - .HasColumnName("force_refresh"); - - 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("LegacyId") - .IsRequired() - .ValueGeneratedOnAdd() - .HasColumnType("text") - .HasColumnName("legacy_id") - .HasDefaultValueSql("gen_random_uuid()"); - - b.PrimitiveCollection("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("Sid") - .IsRequired() - .ValueGeneratedOnAdd() - .HasColumnType("text") - .HasColumnName("sid") - .HasDefaultValueSql("find_free_member_sid()"); - - b.Property("Unlisted") - .HasColumnType("boolean") - .HasColumnName("unlisted"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_members"); - - b.HasIndex("LegacyId") - .IsUnique() - .HasDatabaseName("ix_members_legacy_id"); - - b.HasIndex("Sid") - .IsUnique() - .HasDatabaseName("ix_members_sid"); - - b.HasIndex("UserId", "Name") - .IsUnique() - .HasDatabaseName("ix_members_user_id_name"); - - b.ToTable("members", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.MemberFlag", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("MemberId") - .HasColumnType("bigint") - .HasColumnName("member_id"); - - b.Property("PrideFlagId") - .HasColumnType("bigint") - .HasColumnName("pride_flag_id"); - - b.HasKey("Id") - .HasName("pk_member_flags"); - - b.HasIndex("MemberId") - .HasDatabaseName("ix_member_flags_member_id"); - - b.HasIndex("PrideFlagId") - .HasDatabaseName("ix_member_flags_pride_flag_id"); - - b.ToTable("member_flags", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notice", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("AuthorId") - .HasColumnType("bigint") - .HasColumnName("author_id"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasColumnName("end_time"); - - b.Property("Message") - .IsRequired() - .HasColumnType("text") - .HasColumnName("message"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasColumnName("start_time"); - - b.HasKey("Id") - .HasName("pk_notices"); - - b.HasIndex("AuthorId") - .HasDatabaseName("ix_notices_author_id"); - - b.ToTable("notices", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notification", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("AcknowledgedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("acknowledged_at"); - - b.Property("LocalizationKey") - .HasColumnType("text") - .HasColumnName("localization_key"); - - b.Property>("LocalizationParams") - .IsRequired() - .HasColumnType("hstore") - .HasColumnName("localization_params"); - - b.Property("Message") - .HasColumnType("text") - .HasColumnName("message"); - - b.Property("TargetId") - .HasColumnType("bigint") - .HasColumnName("target_id"); - - b.Property("Type") - .HasColumnType("integer") - .HasColumnName("type"); - - b.HasKey("Id") - .HasName("pk_notifications"); - - b.HasIndex("TargetId") - .HasDatabaseName("ix_notifications_target_id"); - - b.ToTable("notifications", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.PrideFlag", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("Description") - .HasColumnType("text") - .HasColumnName("description"); - - b.Property("Hash") - .HasColumnType("text") - .HasColumnName("hash"); - - b.Property("LegacyId") - .IsRequired() - .ValueGeneratedOnAdd() - .HasColumnType("text") - .HasColumnName("legacy_id") - .HasDefaultValueSql("gen_random_uuid()"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_pride_flags"); - - b.HasIndex("LegacyId") - .IsUnique() - .HasDatabaseName("ix_pride_flags_legacy_id"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_pride_flags_user_id"); - - b.ToTable("pride_flags", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Report", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("Context") - .HasColumnType("text") - .HasColumnName("context"); - - b.Property("Reason") - .HasColumnType("integer") - .HasColumnName("reason"); - - b.Property("ReporterId") - .HasColumnType("bigint") - .HasColumnName("reporter_id"); - - b.Property("Status") - .HasColumnType("integer") - .HasColumnName("status"); - - b.Property("TargetMemberId") - .HasColumnType("bigint") - .HasColumnName("target_member_id"); - - b.Property("TargetSnapshot") - .HasColumnType("text") - .HasColumnName("target_snapshot"); - - b.Property("TargetType") - .HasColumnType("integer") - .HasColumnName("target_type"); - - b.Property("TargetUserId") - .HasColumnType("bigint") - .HasColumnName("target_user_id"); - - b.HasKey("Id") - .HasName("pk_reports"); - - b.HasIndex("ReporterId") - .HasDatabaseName("ix_reports_reporter_id"); - - b.HasIndex("TargetMemberId") - .HasDatabaseName("ix_reports_target_member_id"); - - b.HasIndex("TargetUserId") - .HasDatabaseName("ix_reports_target_user_id"); - - b.ToTable("reports", (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.PrimitiveCollection("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("LastSidReroll") - .HasColumnType("timestamp with time zone") - .HasColumnName("last_sid_reroll"); - - b.Property("LegacyId") - .IsRequired() - .ValueGeneratedOnAdd() - .HasColumnType("text") - .HasColumnName("legacy_id") - .HasDefaultValueSql("gen_random_uuid()"); - - b.PrimitiveCollection("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("Sid") - .IsRequired() - .ValueGeneratedOnAdd() - .HasColumnType("text") - .HasColumnName("sid") - .HasDefaultValueSql("find_free_user_sid()"); - - b.Property("Timezone") - .HasColumnType("text") - .HasColumnName("timezone"); - - b.Property("Username") - .IsRequired() - .HasColumnType("text") - .HasColumnName("username"); - - b.HasKey("Id") - .HasName("pk_users"); - - b.HasIndex("LegacyId") - .IsUnique() - .HasDatabaseName("ix_users_legacy_id"); - - b.HasIndex("Sid") - .IsUnique() - .HasDatabaseName("ix_users_sid"); - - b.HasIndex("Username") - .IsUnique() - .HasDatabaseName("ix_users_username"); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.UserFlag", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("PrideFlagId") - .HasColumnType("bigint") - .HasColumnName("pride_flag_id"); - - b.Property("UserId") - .HasColumnType("bigint") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_user_flags"); - - b.HasIndex("PrideFlagId") - .HasDatabaseName("ix_user_flags_pride_flag_id"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_user_flags_user_id"); - - b.ToTable("user_flags", (string)null); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.AuditLogEntry", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.Report", "Report") - .WithOne("AuditLogEntry") - .HasForeignKey("Foxnouns.Backend.Database.Models.AuditLogEntry", "ReportId") - .OnDelete(DeleteBehavior.SetNull) - .HasConstraintName("fk_audit_log_reports_report_id"); - - b.Navigation("Report"); - }); - - 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.DataExport", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", "User") - .WithMany("DataExports") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_data_exports_users_user_id"); - - 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.MemberFlag", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.Member", null) - .WithMany("ProfileFlags") - .HasForeignKey("MemberId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_member_flags_members_member_id"); - - b.HasOne("Foxnouns.Backend.Database.Models.PrideFlag", "PrideFlag") - .WithMany() - .HasForeignKey("PrideFlagId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_member_flags_pride_flags_pride_flag_id"); - - b.Navigation("PrideFlag"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notice", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", "Author") - .WithMany() - .HasForeignKey("AuthorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_notices_users_author_id"); - - b.Navigation("Author"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notification", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", "Target") - .WithMany() - .HasForeignKey("TargetId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_notifications_users_target_id"); - - b.Navigation("Target"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.PrideFlag", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", null) - .WithMany("Flags") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_pride_flags_users_user_id"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Report", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", "Reporter") - .WithMany() - .HasForeignKey("ReporterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_reports_users_reporter_id"); - - b.HasOne("Foxnouns.Backend.Database.Models.Member", "TargetMember") - .WithMany() - .HasForeignKey("TargetMemberId") - .HasConstraintName("fk_reports_members_target_member_id"); - - b.HasOne("Foxnouns.Backend.Database.Models.User", "TargetUser") - .WithMany() - .HasForeignKey("TargetUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_reports_users_target_user_id"); - - b.Navigation("Reporter"); - - b.Navigation("TargetMember"); - - b.Navigation("TargetUser"); - }); - - 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.UserFlag", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.PrideFlag", "PrideFlag") - .WithMany() - .HasForeignKey("PrideFlagId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_flags_pride_flags_pride_flag_id"); - - b.HasOne("Foxnouns.Backend.Database.Models.User", null) - .WithMany("ProfileFlags") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_flags_users_user_id"); - - b.Navigation("PrideFlag"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Member", b => - { - b.Navigation("ProfileFlags"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Report", b => - { - b.Navigation("AuditLogEntry"); - }); - - modelBuilder.Entity("Foxnouns.Backend.Database.Models.User", b => - { - b.Navigation("AuthMethods"); - - b.Navigation("DataExports"); - - b.Navigation("Flags"); - - b.Navigation("Members"); - - b.Navigation("ProfileFlags"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Foxnouns.Backend/Database/Migrations/20250329131053_AddNotices.cs b/Foxnouns.Backend/Database/Migrations/20250329131053_AddNotices.cs deleted file mode 100644 index 24c5166..0000000 --- a/Foxnouns.Backend/Database/Migrations/20250329131053_AddNotices.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; -using NodaTime; - -#nullable disable - -namespace Foxnouns.Backend.Database.Migrations -{ - /// - public partial class AddNotices : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "notices", - columns: table => new - { - id = table.Column(type: "bigint", nullable: false), - message = table.Column(type: "text", nullable: false), - start_time = table.Column( - type: "timestamp with time zone", - nullable: false - ), - end_time = table.Column( - type: "timestamp with time zone", - nullable: false - ), - author_id = table.Column(type: "bigint", nullable: false), - }, - constraints: table => - { - table.PrimaryKey("pk_notices", x => x.id); - table.ForeignKey( - name: "fk_notices_users_author_id", - column: x => x.author_id, - principalTable: "users", - principalColumn: "id", - onDelete: ReferentialAction.Cascade - ); - } - ); - - migrationBuilder.CreateIndex( - name: "ix_notices_author_id", - table: "notices", - column: "author_id" - ); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable(name: "notices"); - } - } -} diff --git a/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs b/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs index 70b035d..922a599 100644 --- a/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs +++ b/Foxnouns.Backend/Database/Migrations/DatabaseContextModelSnapshot.cs @@ -343,38 +343,6 @@ namespace Foxnouns.Backend.Database.Migrations b.ToTable("member_flags", (string)null); }); - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notice", b => - { - b.Property("Id") - .HasColumnType("bigint") - .HasColumnName("id"); - - b.Property("AuthorId") - .HasColumnType("bigint") - .HasColumnName("author_id"); - - b.Property("EndTime") - .HasColumnType("timestamp with time zone") - .HasColumnName("end_time"); - - b.Property("Message") - .IsRequired() - .HasColumnType("text") - .HasColumnName("message"); - - b.Property("StartTime") - .HasColumnType("timestamp with time zone") - .HasColumnName("start_time"); - - b.HasKey("Id") - .HasName("pk_notices"); - - b.HasIndex("AuthorId") - .HasDatabaseName("ix_notices_author_id"); - - b.ToTable("notices", (string)null); - }); - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notification", b => { b.Property("Id") @@ -782,18 +750,6 @@ namespace Foxnouns.Backend.Database.Migrations b.Navigation("PrideFlag"); }); - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notice", b => - { - b.HasOne("Foxnouns.Backend.Database.Models.User", "Author") - .WithMany() - .HasForeignKey("AuthorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_notices_users_author_id"); - - b.Navigation("Author"); - }); - modelBuilder.Entity("Foxnouns.Backend.Database.Models.Notification", b => { b.HasOne("Foxnouns.Backend.Database.Models.User", "Target") diff --git a/Foxnouns.Backend/Database/Models/Notice.cs b/Foxnouns.Backend/Database/Models/Notice.cs deleted file mode 100644 index c3e6f0d..0000000 --- a/Foxnouns.Backend/Database/Models/Notice.cs +++ /dev/null @@ -1,13 +0,0 @@ -using NodaTime; - -namespace Foxnouns.Backend.Database.Models; - -public class Notice : BaseModel -{ - public required string Message { get; set; } - public required Instant StartTime { get; set; } - public required Instant EndTime { get; set; } - - public Snowflake AuthorId { get; init; } - public User Author { get; init; } = null!; -} diff --git a/Foxnouns.Backend/Database/Models/User.cs b/Foxnouns.Backend/Database/Models/User.cs index 0e6eb43..3ad7ae3 100644 --- a/Foxnouns.Backend/Database/Models/User.cs +++ b/Foxnouns.Backend/Database/Models/User.cs @@ -95,5 +95,4 @@ public enum PreferenceSize public class UserSettings { public bool? DarkMode { get; set; } - public Snowflake? LastReadNotice { get; set; } } diff --git a/Foxnouns.Backend/Dto/Meta.cs b/Foxnouns.Backend/Dto/Meta.cs index 168327a..0ff6e80 100644 --- a/Foxnouns.Backend/Dto/Meta.cs +++ b/Foxnouns.Backend/Dto/Meta.cs @@ -14,8 +14,6 @@ // along with this program. If not, see . // ReSharper disable NotAccessedPositionalProperty.Global -using Foxnouns.Backend.Database; - namespace Foxnouns.Backend.Dto; public record MetaResponse( @@ -24,12 +22,9 @@ public record MetaResponse( string Hash, int Members, UserInfoResponse Users, - LimitsResponse Limits, - MetaNoticeResponse? Notice + LimitsResponse Limits ); -public record MetaNoticeResponse(Snowflake Id, string Message); - public record UserInfoResponse(int Total, int ActiveMonth, int ActiveWeek, int ActiveDay); public record LimitsResponse( diff --git a/Foxnouns.Backend/Dto/Moderation.cs b/Foxnouns.Backend/Dto/Moderation.cs index bcc7e8e..26fd0aa 100644 --- a/Foxnouns.Backend/Dto/Moderation.cs +++ b/Foxnouns.Backend/Dto/Moderation.cs @@ -122,13 +122,3 @@ public record QueryUserResponse( ); public record QuerySensitiveUserDataRequest(string Reason); - -public record NoticeResponse( - Snowflake Id, - string Message, - Instant StartTime, - Instant EndTime, - PartialUser Author -); - -public record CreateNoticeRequest(string Message, Instant? StartTime, Instant EndTime); diff --git a/Foxnouns.Backend/Dto/User.cs b/Foxnouns.Backend/Dto/User.cs index 2ae38f1..db4780a 100644 --- a/Foxnouns.Backend/Dto/User.cs +++ b/Foxnouns.Backend/Dto/User.cs @@ -49,8 +49,7 @@ public record UserResponse( [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] Instant? LastSidReroll, [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] string? Timezone, [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] bool? Suspended, - [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] bool? Deleted, - [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] UserSettings? Settings + [property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] bool? Deleted ); public record CustomPreferenceResponse( @@ -80,7 +79,6 @@ public record PartialUser( public class UpdateUserSettingsRequest : PatchRequest { public bool? DarkMode { get; init; } - public Snowflake? LastReadNotice { get; init; } } public class CustomPreferenceUpdateRequest diff --git a/Foxnouns.Backend/Extensions/WebApplicationExtensions.cs b/Foxnouns.Backend/Extensions/WebApplicationExtensions.cs index c3efda6..567ae02 100644 --- a/Foxnouns.Backend/Extensions/WebApplicationExtensions.cs +++ b/Foxnouns.Backend/Extensions/WebApplicationExtensions.cs @@ -15,12 +15,10 @@ using Coravel; using Coravel.Queuing.Interfaces; using Foxnouns.Backend.Database; -using Foxnouns.Backend.Database.Models; using Foxnouns.Backend.Jobs; using Foxnouns.Backend.Middleware; using Foxnouns.Backend.Services; using Foxnouns.Backend.Services.Auth; -using Foxnouns.Backend.Services.Caching; using Foxnouns.Backend.Services.V1; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Http.Resilience; @@ -164,7 +162,6 @@ public static class WebApplicationExtensions .AddScoped() .AddTransient() .AddTransient() - .AddSingleton() // Background services .AddHostedService() // Transient jobs diff --git a/Foxnouns.Backend/Program.cs b/Foxnouns.Backend/Program.cs index b266248..f27ad50 100644 --- a/Foxnouns.Backend/Program.cs +++ b/Foxnouns.Backend/Program.cs @@ -68,7 +68,6 @@ builder { NamingStrategy = new SnakeCaseNamingStrategy(), }; - options.SerializerSettings.DateParseHandling = DateParseHandling.None; }) .ConfigureApiBehaviorOptions(options => { diff --git a/Foxnouns.Backend/Services/Auth/AuthService.cs b/Foxnouns.Backend/Services/Auth/AuthService.cs index e3e3edb..80d05ac 100644 --- a/Foxnouns.Backend/Services/Auth/AuthService.cs +++ b/Foxnouns.Backend/Services/Auth/AuthService.cs @@ -253,14 +253,14 @@ public class AuthService( { AssertValidAuthType(authType, app); - // This is already checked when generating an add account state, but we check it here too just in case. + // This is already checked when int currentCount = await db .AuthMethods.Where(m => m.UserId == userId && m.AuthType == authType) .CountAsync(ct); if (currentCount >= AuthUtils.MaxAuthMethodsPerType) { throw new ApiError.BadRequest( - $"Too many linked accounts of this type, maximum of {AuthUtils.MaxAuthMethodsPerType} per account." + "Too many linked accounts of this type, maximum of 3 per account." ); } diff --git a/Foxnouns.Backend/Services/Caching/NoticeCacheService.cs b/Foxnouns.Backend/Services/Caching/NoticeCacheService.cs deleted file mode 100644 index 2a0b1f9..0000000 --- a/Foxnouns.Backend/Services/Caching/NoticeCacheService.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (C) 2023-present sam/u1f320 (vulpine.solutions) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -using Foxnouns.Backend.Database; -using Foxnouns.Backend.Database.Models; -using Microsoft.EntityFrameworkCore; -using NodaTime; - -namespace Foxnouns.Backend.Services.Caching; - -public class NoticeCacheService(IServiceProvider serviceProvider, IClock clock, ILogger logger) - : SingletonCacheService(serviceProvider, clock, logger) -{ - public override Duration MaxAge { get; init; } = Duration.FromMinutes(5); - - public override Func< - DatabaseContext, - CancellationToken, - Task - > FetchFunc { get; init; } = - async (db, ct) => - await db - .Notices.Where(n => - n.StartTime < clock.GetCurrentInstant() && n.EndTime > clock.GetCurrentInstant() - ) - .OrderByDescending(n => n.Id) - .FirstOrDefaultAsync(ct); -} diff --git a/Foxnouns.Backend/Services/Caching/SingletonCacheService.cs b/Foxnouns.Backend/Services/Caching/SingletonCacheService.cs deleted file mode 100644 index 87b19a7..0000000 --- a/Foxnouns.Backend/Services/Caching/SingletonCacheService.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2023-present sam/u1f320 (vulpine.solutions) -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . -using Foxnouns.Backend.Database; -using NodaTime; - -namespace Foxnouns.Backend.Services.Caching; - -public abstract class SingletonCacheService( - IServiceProvider serviceProvider, - IClock clock, - ILogger logger -) - where T : class -{ - private T? _item; - private Instant _lastUpdated = Instant.MinValue; - private readonly SemaphoreSlim _semaphore = new(1, 1); - private readonly ILogger _logger = logger.ForContext>(); - - public virtual Duration MaxAge { get; init; } = Duration.FromMinutes(5); - - public virtual Func> FetchFunc { get; init; } = - (_, __) => Task.FromResult(null); - - public async Task GetAsync(CancellationToken ct = default) - { - await _semaphore.WaitAsync(ct); - try - { - if (_lastUpdated > clock.GetCurrentInstant() - MaxAge) - { - return _item; - } - - _logger.Debug("Cached item of type {Type} is expired, fetching it.", typeof(T)); - - await using AsyncServiceScope scope = serviceProvider.CreateAsyncScope(); - await using DatabaseContext db = - scope.ServiceProvider.GetRequiredService(); - - T? item = await FetchFunc(db, ct); - _item = item; - _lastUpdated = clock.GetCurrentInstant(); - return item; - } - finally - { - _semaphore.Release(); - } - } -} diff --git a/Foxnouns.Backend/Services/UserRendererService.cs b/Foxnouns.Backend/Services/UserRendererService.cs index 0c1fc1b..5a90c2d 100644 --- a/Foxnouns.Backend/Services/UserRendererService.cs +++ b/Foxnouns.Backend/Services/UserRendererService.cs @@ -33,7 +33,6 @@ public class UserRendererService( bool renderMembers = true, bool renderAuthMethods = false, string? overrideSid = null, - bool renderSettings = false, CancellationToken ct = default ) => await RenderUserInnerAsync( @@ -43,7 +42,6 @@ public class UserRendererService( renderMembers, renderAuthMethods, overrideSid, - renderSettings, ct ); @@ -54,7 +52,6 @@ public class UserRendererService( bool renderMembers = true, bool renderAuthMethods = false, string? overrideSid = null, - bool renderSettings = false, CancellationToken ct = default ) { @@ -65,7 +62,6 @@ public class UserRendererService( renderMembers = renderMembers && (!user.ListHidden || tokenCanReadHiddenMembers); renderAuthMethods = renderAuthMethods && tokenPrivileged; - renderSettings = renderSettings && tokenHidden; IEnumerable members = renderMembers ? await db.Members.Where(m => m.UserId == user.Id).OrderBy(m => m.Name).ToListAsync(ct) @@ -121,8 +117,7 @@ public class UserRendererService( tokenHidden ? user.LastSidReroll : null, tokenHidden ? user.Timezone ?? "" : null, tokenHidden ? user is { Deleted: true, DeletedBy: not null } : null, - tokenHidden ? user.Deleted : null, - renderSettings ? user.Settings : null + tokenHidden ? user.Deleted : null ); } diff --git a/Foxnouns.Frontend/src/lib/api/models/meta.ts b/Foxnouns.Frontend/src/lib/api/models/meta.ts index 28ea494..56f31c9 100644 --- a/Foxnouns.Frontend/src/lib/api/models/meta.ts +++ b/Foxnouns.Frontend/src/lib/api/models/meta.ts @@ -10,7 +10,6 @@ export type Meta = { }; members: number; limits: Limits; - notice: { id: string; message: string } | null; }; export type Limits = { diff --git a/Foxnouns.Frontend/src/lib/api/models/user.ts b/Foxnouns.Frontend/src/lib/api/models/user.ts index be9d961..6cd8e4c 100644 --- a/Foxnouns.Frontend/src/lib/api/models/user.ts +++ b/Foxnouns.Frontend/src/lib/api/models/user.ts @@ -28,7 +28,6 @@ export type MeUser = UserWithMembers & { timezone: string; suspended: boolean; deleted: boolean; - settings: UserSettings; }; export type UserWithMembers = User & { members: PartialMember[] | null }; @@ -41,7 +40,6 @@ export type UserWithHiddenFields = User & { export type UserSettings = { dark_mode: boolean | null; - last_read_notice: string | null; }; export type PartialMember = { diff --git a/Foxnouns.Frontend/src/lib/components/GlobalNotice.svelte b/Foxnouns.Frontend/src/lib/components/GlobalNotice.svelte deleted file mode 100644 index 3d1c718..0000000 --- a/Foxnouns.Frontend/src/lib/components/GlobalNotice.svelte +++ /dev/null @@ -1,49 +0,0 @@ - - -{#if renderNotice} - -{/if} diff --git a/Foxnouns.Frontend/src/lib/components/settings/Notification.svelte b/Foxnouns.Frontend/src/lib/components/settings/Notification.svelte index 796d60a..c452f4c 100644 --- a/Foxnouns.Frontend/src/lib/components/settings/Notification.svelte +++ b/Foxnouns.Frontend/src/lib/components/settings/Notification.svelte @@ -38,6 +38,6 @@ diff --git a/Foxnouns.Frontend/src/lib/i18n/locales/en.json b/Foxnouns.Frontend/src/lib/i18n/locales/en.json index dc74d2f..9f54943 100644 --- a/Foxnouns.Frontend/src/lib/i18n/locales/en.json +++ b/Foxnouns.Frontend/src/lib/i18n/locales/en.json @@ -350,8 +350,6 @@ "notification": { "suspension": "Your account has been suspended for the following reason: {{reason}}", "warning": "You have been warned for the following reason: {{reason}}", - "warning-cleared-fields": "You have been warned for the following reason: {{reason}}\n\nAdditionally, the following fields have been cleared from your profile:\n{{clearedFields}}", - "mark-as-read": "Mark as read", - "no-notifications": "You have no notifications." + "warning-cleared-fields": "You have been warned for the following reason: {{reason}}\n\nAdditionally, the following fields have been cleared from your profile:\n{{clearedFields}}" } } diff --git a/Foxnouns.Frontend/src/routes/+page.svelte b/Foxnouns.Frontend/src/routes/+page.svelte index 4fd36dc..47ab0e5 100644 --- a/Foxnouns.Frontend/src/routes/+page.svelte +++ b/Foxnouns.Frontend/src/routes/+page.svelte @@ -1,5 +1,4 @@ {$t("title.settings")} • pronouns.cc -{#if data.meta.notice} -
- -
-{/if} -