Compare commits
No commits in common. "7791c9196091d9c6bbeb2fda46f0913b925cc4b7" and "e24c4f9b0033fc82092a7c5c87bd56792d549cb6" have entirely different histories.
7791c91960
...
e24c4f9b00
23 changed files with 7 additions and 484 deletions
|
@ -22,7 +22,6 @@ using Foxnouns.Backend.Services;
|
|||
using Foxnouns.Backend.Utils;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using XidNet;
|
||||
|
||||
namespace Foxnouns.Backend.Controllers;
|
||||
|
||||
|
@ -65,7 +64,6 @@ public class FlagsController(
|
|||
var flag = new PrideFlag
|
||||
{
|
||||
Id = snowflakeGenerator.GenerateSnowflake(),
|
||||
LegacyId = Xid.NewXid().ToString(),
|
||||
UserId = CurrentUser!.Id,
|
||||
Name = req.Name,
|
||||
Description = req.Description,
|
||||
|
|
|
@ -26,7 +26,6 @@ using Microsoft.AspNetCore.Mvc;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using NodaTime;
|
||||
using XidNet;
|
||||
|
||||
namespace Foxnouns.Backend.Controllers;
|
||||
|
||||
|
@ -102,7 +101,6 @@ public class MembersController(
|
|||
var member = new Member
|
||||
{
|
||||
Id = snowflakeGenerator.GenerateSnowflake(),
|
||||
LegacyId = Xid.NewXid().ToString(),
|
||||
User = CurrentUser!,
|
||||
Name = req.Name,
|
||||
DisplayName = req.DisplayName,
|
||||
|
|
|
@ -222,7 +222,7 @@ public class UsersController(
|
|||
.CustomPreferences.Where(x => req.Any(r => r.Id == x.Key))
|
||||
.ToDictionary();
|
||||
|
||||
foreach (CustomPreferenceUpdateRequest r in req)
|
||||
foreach (CustomPreferenceUpdateRequest? r in req)
|
||||
{
|
||||
if (r.Id != null && preferences.ContainsKey(r.Id.Value))
|
||||
{
|
||||
|
@ -233,7 +233,6 @@ public class UsersController(
|
|||
Muted = r.Muted,
|
||||
Size = r.Size,
|
||||
Tooltip = r.Tooltip,
|
||||
LegacyId = preferences[r.Id.Value].LegacyId,
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@ -245,7 +244,6 @@ public class UsersController(
|
|||
Muted = r.Muted,
|
||||
Size = r.Size,
|
||||
Tooltip = r.Tooltip,
|
||||
LegacyId = Guid.NewGuid(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
using Foxnouns.Backend.Database.Models;
|
||||
using Foxnouns.Backend.Services.V1;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxnouns.Backend.Controllers.V1;
|
||||
|
||||
[Route("/api/v1/users")]
|
||||
public class UsersV1Controller(UsersV1Service usersV1Service) : ApiControllerBase
|
||||
{
|
||||
[HttpGet("{userRef}")]
|
||||
public async Task<IActionResult> GetUserAsync(string userRef, CancellationToken ct = default)
|
||||
{
|
||||
User user = await usersV1Service.ResolveUserAsync(userRef, CurrentToken, ct);
|
||||
return Ok(await usersV1Service.RenderUserAsync(user));
|
||||
}
|
||||
}
|
|
@ -139,26 +139,6 @@ public class DatabaseContext(DbContextOptions options) : DbContext(options)
|
|||
modelBuilder
|
||||
.HasDbFunction(typeof(DatabaseContext).GetMethod(nameof(FindFreeMemberSid))!)
|
||||
.HasName("find_free_member_sid");
|
||||
|
||||
// Indexes for legacy IDs for APIv1
|
||||
modelBuilder.Entity<User>().HasIndex(u => u.LegacyId).IsUnique();
|
||||
modelBuilder.Entity<Member>().HasIndex(m => m.LegacyId).IsUnique();
|
||||
modelBuilder.Entity<PrideFlag>().HasIndex(f => f.LegacyId).IsUnique();
|
||||
|
||||
// a UUID is not an xid, but this should always be set by the application anyway.
|
||||
// we're just setting it here to shut EFCore up because squashing migrations is for nerds
|
||||
modelBuilder
|
||||
.Entity<User>()
|
||||
.Property(u => u.LegacyId)
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
modelBuilder
|
||||
.Entity<Member>()
|
||||
.Property(m => m.LegacyId)
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
modelBuilder
|
||||
.Entity<PrideFlag>()
|
||||
.Property(f => f.LegacyId)
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Foxnouns.Backend.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20241225155818_AddLegacyIds")]
|
||||
public partial class AddLegacyIds : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "legacy_id",
|
||||
table: "users",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValueSql: "gen_random_uuid()"
|
||||
);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "legacy_id",
|
||||
table: "pride_flags",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValueSql: "gen_random_uuid()"
|
||||
);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "legacy_id",
|
||||
table: "members",
|
||||
type: "text",
|
||||
nullable: false,
|
||||
defaultValueSql: "gen_random_uuid()"
|
||||
);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_users_legacy_id",
|
||||
table: "users",
|
||||
column: "legacy_id",
|
||||
unique: true
|
||||
);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_pride_flags_legacy_id",
|
||||
table: "pride_flags",
|
||||
column: "legacy_id",
|
||||
unique: true
|
||||
);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_members_legacy_id",
|
||||
table: "members",
|
||||
column: "legacy_id",
|
||||
unique: true
|
||||
);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(name: "ix_users_legacy_id", table: "users");
|
||||
|
||||
migrationBuilder.DropIndex(name: "ix_pride_flags_legacy_id", table: "pride_flags");
|
||||
|
||||
migrationBuilder.DropIndex(name: "ix_members_legacy_id", table: "members");
|
||||
|
||||
migrationBuilder.DropColumn(name: "legacy_id", table: "users");
|
||||
|
||||
migrationBuilder.DropColumn(name: "legacy_id", table: "pride_flags");
|
||||
|
||||
migrationBuilder.DropColumn(name: "legacy_id", table: "members");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -254,13 +254,6 @@ namespace Foxnouns.Backend.Database.Migrations
|
|||
.HasColumnType("jsonb")
|
||||
.HasColumnName("fields");
|
||||
|
||||
b.Property<string>("LegacyId")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("legacy_id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.PrimitiveCollection<string[]>("Links")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]")
|
||||
|
@ -299,10 +292,6 @@ namespace Foxnouns.Backend.Database.Migrations
|
|||
b.HasKey("Id")
|
||||
.HasName("pk_members");
|
||||
|
||||
b.HasIndex("LegacyId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_members_legacy_id");
|
||||
|
||||
b.HasIndex("Sid")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_members_sid");
|
||||
|
@ -397,13 +386,6 @@ namespace Foxnouns.Backend.Database.Migrations
|
|||
.HasColumnType("text")
|
||||
.HasColumnName("hash");
|
||||
|
||||
b.Property<string>("LegacyId")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("legacy_id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
|
@ -416,10 +398,6 @@ namespace Foxnouns.Backend.Database.Migrations
|
|||
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");
|
||||
|
||||
|
@ -604,13 +582,6 @@ namespace Foxnouns.Backend.Database.Migrations
|
|||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("last_sid_reroll");
|
||||
|
||||
b.Property<string>("LegacyId")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("legacy_id")
|
||||
.HasDefaultValueSql("gen_random_uuid()");
|
||||
|
||||
b.PrimitiveCollection<string[]>("Links")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]")
|
||||
|
@ -666,10 +637,6 @@ namespace Foxnouns.Backend.Database.Migrations
|
|||
b.HasKey("Id")
|
||||
.HasName("pk_users");
|
||||
|
||||
b.HasIndex("LegacyId")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_legacy_id");
|
||||
|
||||
b.HasIndex("Sid")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_users_sid");
|
||||
|
|
|
@ -18,7 +18,6 @@ public class Member : BaseModel
|
|||
{
|
||||
public required string Name { get; set; }
|
||||
public string Sid { get; set; } = string.Empty;
|
||||
public required string LegacyId { get; init; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Bio { get; set; }
|
||||
public string? Avatar { get; set; }
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace Foxnouns.Backend.Database.Models;
|
|||
public class PrideFlag : BaseModel
|
||||
{
|
||||
public required Snowflake UserId { get; init; }
|
||||
public required string LegacyId { get; init; }
|
||||
|
||||
// A null hash means the flag hasn't been processed yet.
|
||||
public string? Hash { get; set; }
|
||||
|
|
|
@ -25,7 +25,6 @@ public class User : BaseModel
|
|||
{
|
||||
public required string Username { get; set; }
|
||||
public string Sid { get; set; } = string.Empty;
|
||||
public required string LegacyId { get; init; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Bio { get; set; }
|
||||
public string? MemberTitle { get; set; }
|
||||
|
@ -70,8 +69,6 @@ public class User : BaseModel
|
|||
// This type is generally serialized directly, so the converter is applied here.
|
||||
[JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))]
|
||||
public PreferenceSize Size { get; set; }
|
||||
|
||||
public Guid LegacyId { get; init; } = Guid.NewGuid();
|
||||
}
|
||||
|
||||
public static readonly Duration DeleteAfter = Duration.FromDays(30);
|
||||
|
|
|
@ -36,7 +36,7 @@ public record UserResponse(
|
|||
IEnumerable<FieldEntry> Names,
|
||||
IEnumerable<Pronoun> Pronouns,
|
||||
IEnumerable<Field> Fields,
|
||||
Dictionary<Snowflake, CustomPreferenceResponse> CustomPreferences,
|
||||
Dictionary<Snowflake, User.CustomPreference> CustomPreferences,
|
||||
IEnumerable<PrideFlagResponse> Flags,
|
||||
int? UtcOffset,
|
||||
[property: JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))] UserRole Role,
|
||||
|
@ -52,14 +52,6 @@ public record UserResponse(
|
|||
[property: JsonProperty(NullValueHandling = NullValueHandling.Ignore)] bool? Deleted
|
||||
);
|
||||
|
||||
public record CustomPreferenceResponse(
|
||||
string Icon,
|
||||
string Tooltip,
|
||||
bool Muted,
|
||||
bool Favourite,
|
||||
[property: JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))] PreferenceSize Size
|
||||
);
|
||||
|
||||
public record AuthMethodResponse(
|
||||
Snowflake Id,
|
||||
[property: JsonConverter(typeof(ScreamingSnakeCaseEnumConverter))] AuthType Type,
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
// ReSharper disable NotAccessedPositionalProperty.Global
|
||||
using Foxnouns.Backend.Database;
|
||||
using Foxnouns.Backend.Database.Models;
|
||||
using Foxnouns.Backend.Services.V1;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Foxnouns.Backend.Dto.V1;
|
||||
|
||||
public record UserResponse(
|
||||
string Id,
|
||||
Snowflake IdNew,
|
||||
string Sid,
|
||||
string Name,
|
||||
string? DisplayName,
|
||||
string? Bio,
|
||||
string? MemberTitle,
|
||||
string? Avatar,
|
||||
string[] Links,
|
||||
FieldEntry[] Names,
|
||||
PronounEntry[] Pronouns,
|
||||
ProfileField[] Fields,
|
||||
int? UtcOffset,
|
||||
Dictionary<Guid, CustomPreference> CustomPreferences
|
||||
);
|
||||
|
||||
public record CustomPreference(
|
||||
string Icon,
|
||||
string Tooltip,
|
||||
[property: JsonConverter(typeof(StringEnumConverter), typeof(SnakeCaseNamingStrategy))]
|
||||
PreferenceSize Size,
|
||||
bool Muted,
|
||||
bool Favourite
|
||||
);
|
||||
|
||||
public record ProfileField(string Name, FieldEntry[] Entries)
|
||||
{
|
||||
public static ProfileField FromField(
|
||||
Field field,
|
||||
Dictionary<Snowflake, User.CustomPreference> customPreferences
|
||||
) => new(field.Name, FieldEntry.FromEntries(field.Entries, customPreferences));
|
||||
|
||||
public static ProfileField[] FromFields(
|
||||
IEnumerable<Field> fields,
|
||||
Dictionary<Snowflake, User.CustomPreference> customPreferences
|
||||
) => fields.Select(f => FromField(f, customPreferences)).ToArray();
|
||||
}
|
||||
|
||||
public record FieldEntry(string Value, string Status)
|
||||
{
|
||||
public static FieldEntry[] FromEntries(
|
||||
IEnumerable<Foxnouns.Backend.Database.Models.FieldEntry> entries,
|
||||
Dictionary<Snowflake, User.CustomPreference> customPreferences
|
||||
) =>
|
||||
entries
|
||||
.Select(e => new FieldEntry(
|
||||
e.Value,
|
||||
V1Utils.TranslateStatus(e.Status, customPreferences)
|
||||
))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public record PronounEntry(string Pronouns, string? DisplayText, string Status)
|
||||
{
|
||||
public static PronounEntry[] FromPronouns(
|
||||
IEnumerable<Pronoun> pronouns,
|
||||
Dictionary<Snowflake, User.CustomPreference> customPreferences
|
||||
) =>
|
||||
pronouns
|
||||
.Select(p => new PronounEntry(
|
||||
p.Value,
|
||||
p.DisplayText,
|
||||
V1Utils.TranslateStatus(p.Status, customPreferences)
|
||||
))
|
||||
.ToArray();
|
||||
}
|
|
@ -19,7 +19,6 @@ using Foxnouns.Backend.Jobs;
|
|||
using Foxnouns.Backend.Middleware;
|
||||
using Foxnouns.Backend.Services;
|
||||
using Foxnouns.Backend.Services.Auth;
|
||||
using Foxnouns.Backend.Services.V1;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Minio;
|
||||
using NodaTime;
|
||||
|
@ -128,9 +127,7 @@ public static class WebApplicationExtensions
|
|||
.AddTransient<MemberAvatarUpdateInvocable>()
|
||||
.AddTransient<UserAvatarUpdateInvocable>()
|
||||
.AddTransient<CreateFlagInvocable>()
|
||||
.AddTransient<CreateDataExportInvocable>()
|
||||
// Legacy services
|
||||
.AddScoped<UsersV1Service>();
|
||||
.AddTransient<CreateDataExportInvocable>();
|
||||
|
||||
if (!config.Logging.EnableMetrics)
|
||||
services.AddHostedService<BackgroundMetricsCollectionService>();
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.6"/>
|
||||
<PackageReference Include="System.Text.Json" Version="9.0.0"/>
|
||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1"/>
|
||||
<PackageReference Include="Yort.Xid.Net" Version="2.0.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="SetSourceRevisionId" BeforeTargets="InitializeSourceControlInformation">
|
||||
|
|
|
@ -20,7 +20,6 @@ using Foxnouns.Backend.Utils;
|
|||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NodaTime;
|
||||
using XidNet;
|
||||
|
||||
namespace Foxnouns.Backend.Services.Auth;
|
||||
|
||||
|
@ -71,7 +70,6 @@ public class AuthService(
|
|||
},
|
||||
LastActive = clock.GetCurrentInstant(),
|
||||
Sid = null!,
|
||||
LegacyId = Xid.NewXid().ToString(),
|
||||
};
|
||||
|
||||
db.Add(user);
|
||||
|
@ -118,7 +116,6 @@ public class AuthService(
|
|||
},
|
||||
LastActive = clock.GetCurrentInstant(),
|
||||
Sid = null!,
|
||||
LegacyId = Xid.NewXid().ToString(),
|
||||
};
|
||||
|
||||
db.Add(user);
|
||||
|
|
|
@ -103,8 +103,7 @@ public class UserRendererService(
|
|||
user.Names,
|
||||
user.Pronouns,
|
||||
user.Fields,
|
||||
user.CustomPreferences.Select(x => (x.Key, RenderCustomPreference(x.Value)))
|
||||
.ToDictionary(),
|
||||
user.CustomPreferences,
|
||||
flags.Select(f => RenderPrideFlag(f.PrideFlag)),
|
||||
utcOffset,
|
||||
user.Role,
|
||||
|
@ -131,14 +130,6 @@ public class UserRendererService(
|
|||
: a.RemoteUsername
|
||||
);
|
||||
|
||||
public static CustomPreferenceResponse RenderCustomPreference(User.CustomPreference pref) =>
|
||||
new(pref.Icon, pref.Tooltip, pref.Muted, pref.Favourite, pref.Size);
|
||||
|
||||
public static Dictionary<Snowflake, CustomPreferenceResponse> RenderCustomPreferences(
|
||||
User user
|
||||
) =>
|
||||
user.CustomPreferences.Select(x => (x.Key, RenderCustomPreference(x.Value))).ToDictionary();
|
||||
|
||||
public PartialUser RenderPartialUser(User user) =>
|
||||
new(
|
||||
user.Id,
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
using Foxnouns.Backend.Database;
|
||||
using Foxnouns.Backend.Database.Models;
|
||||
using Foxnouns.Backend.Dto.V1;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using FieldEntry = Foxnouns.Backend.Dto.V1.FieldEntry;
|
||||
|
||||
namespace Foxnouns.Backend.Services.V1;
|
||||
|
||||
public class UsersV1Service(DatabaseContext db)
|
||||
{
|
||||
public async Task<User> ResolveUserAsync(
|
||||
string userRef,
|
||||
Token? token,
|
||||
CancellationToken ct = default
|
||||
)
|
||||
{
|
||||
if (userRef == "@me")
|
||||
{
|
||||
if (token == null)
|
||||
{
|
||||
throw new ApiError.Unauthorized(
|
||||
"This endpoint requires an authenticated user.",
|
||||
ErrorCode.AuthenticationRequired
|
||||
);
|
||||
}
|
||||
|
||||
return await db.Users.FirstAsync(u => u.Id == token.UserId, ct);
|
||||
}
|
||||
|
||||
User? user;
|
||||
if (Snowflake.TryParse(userRef, out Snowflake? sf))
|
||||
{
|
||||
user = await db.Users.FirstOrDefaultAsync(u => u.Id == sf && !u.Deleted, ct);
|
||||
if (user != null)
|
||||
return user;
|
||||
}
|
||||
|
||||
user = await db.Users.FirstOrDefaultAsync(u => u.LegacyId == userRef && !u.Deleted, ct);
|
||||
if (user != null)
|
||||
return user;
|
||||
|
||||
user = await db.Users.FirstOrDefaultAsync(u => u.Username == userRef && !u.Deleted, ct);
|
||||
if (user != null)
|
||||
return user;
|
||||
|
||||
throw new ApiError.NotFound(
|
||||
"No user with that ID or username found.",
|
||||
ErrorCode.UserNotFound
|
||||
);
|
||||
}
|
||||
|
||||
public async Task<UserResponse> RenderUserAsync(User user)
|
||||
{
|
||||
int? utcOffset = null;
|
||||
if (
|
||||
user.Timezone != null
|
||||
&& TimeZoneInfo.TryFindSystemTimeZoneById(user.Timezone, out TimeZoneInfo? tz)
|
||||
)
|
||||
{
|
||||
utcOffset = (int)tz.GetUtcOffset(DateTimeOffset.UtcNow).TotalSeconds;
|
||||
}
|
||||
|
||||
return new UserResponse(
|
||||
user.LegacyId,
|
||||
user.Id,
|
||||
user.Sid,
|
||||
user.Username,
|
||||
user.DisplayName,
|
||||
user.Bio,
|
||||
user.MemberTitle,
|
||||
user.Avatar,
|
||||
user.Links,
|
||||
FieldEntry.FromEntries(user.Names, user.CustomPreferences),
|
||||
PronounEntry.FromPronouns(user.Pronouns, user.CustomPreferences),
|
||||
ProfileField.FromFields(user.Fields, user.CustomPreferences),
|
||||
utcOffset,
|
||||
user.CustomPreferences.Select(x =>
|
||||
(
|
||||
x.Value.LegacyId,
|
||||
new CustomPreference(
|
||||
x.Value.Icon,
|
||||
x.Value.Tooltip,
|
||||
x.Value.Size,
|
||||
x.Value.Muted,
|
||||
x.Value.Favourite
|
||||
)
|
||||
)
|
||||
)
|
||||
.ToDictionary()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
using Foxnouns.Backend.Database;
|
||||
using Foxnouns.Backend.Database.Models;
|
||||
|
||||
namespace Foxnouns.Backend.Services.V1;
|
||||
|
||||
public static class V1Utils
|
||||
{
|
||||
public static string TranslateStatus(
|
||||
string status,
|
||||
Dictionary<Snowflake, User.CustomPreference> customPreferences
|
||||
)
|
||||
{
|
||||
if (!Snowflake.TryParse(status, out Snowflake? sf))
|
||||
return status;
|
||||
|
||||
return customPreferences.TryGetValue(sf.Value, out User.CustomPreference? cf)
|
||||
? cf.LegacyId.ToString()
|
||||
: "unknown";
|
||||
}
|
||||
}
|
|
@ -293,12 +293,6 @@
|
|||
"System.Runtime": "4.3.1"
|
||||
}
|
||||
},
|
||||
"Yort.Xid.Net": {
|
||||
"type": "Direct",
|
||||
"requested": "[2.0.1, )",
|
||||
"resolved": "2.0.1",
|
||||
"contentHash": "+3sNX7/RKSKheVuMz9jtWLazD+R4PXpx8va2d9SdDgvKOhETbEb0VYis8K/fD1qm/qOQT57LadToSpzReGMZlw=="
|
||||
},
|
||||
"BouncyCastle.Cryptography": {
|
||||
"type": "Transitive",
|
||||
"resolved": "2.5.0",
|
||||
|
|
|
@ -39,7 +39,6 @@ public class UserMigrator(
|
|||
_user = new User
|
||||
{
|
||||
Id = goUser.SnowflakeId,
|
||||
LegacyId = goUser.Id,
|
||||
Username = goUser.Username,
|
||||
DisplayName = goUser.DisplayName,
|
||||
Bio = goUser.Bio,
|
||||
|
@ -140,7 +139,6 @@ public class UserMigrator(
|
|||
new PrideFlag
|
||||
{
|
||||
Id = flag.SnowflakeId,
|
||||
LegacyId = flag.Id,
|
||||
UserId = _user!.Id,
|
||||
Hash = flag.Hash,
|
||||
Name = flag.Name,
|
||||
|
@ -192,7 +190,6 @@ public class UserMigrator(
|
|||
UserId = _user!.Id,
|
||||
Name = goMember.Name,
|
||||
Sid = goMember.Sid,
|
||||
LegacyId = goMember.Id,
|
||||
DisplayName = goMember.DisplayName,
|
||||
Bio = goMember.Bio,
|
||||
Avatar = goMember.Avatar,
|
||||
|
@ -238,7 +235,6 @@ public class UserMigrator(
|
|||
"small" => PreferenceSize.Small,
|
||||
_ => PreferenceSize.Normal,
|
||||
},
|
||||
LegacyId = new Guid(id),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -64,11 +64,3 @@
|
|||
max-width: 200px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.big-footer {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
background-color: bootstrap.shade-color(bootstrap.$dark, 20%);
|
||||
}
|
||||
|
||||
background-color: bootstrap.shade-color(bootstrap.$light, 5%);
|
||||
}
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
<script lang="ts">
|
||||
import type { Meta } from "$api/models";
|
||||
import Git from "svelte-bootstrap-icons/lib/Git.svelte";
|
||||
import Reception4 from "svelte-bootstrap-icons/lib/Reception4.svelte";
|
||||
import Newspaper from "svelte-bootstrap-icons/lib/Newspaper.svelte";
|
||||
import CardText from "svelte-bootstrap-icons/lib/CardText.svelte";
|
||||
import Shield from "svelte-bootstrap-icons/lib/Shield.svelte";
|
||||
import Envelope from "svelte-bootstrap-icons/lib/Envelope.svelte";
|
||||
import CashCoin from "svelte-bootstrap-icons/lib/CashCoin.svelte";
|
||||
import Logo from "./Logo.svelte";
|
||||
|
||||
type Props = { meta: Meta };
|
||||
let { meta }: Props = $props();
|
||||
</script>
|
||||
|
||||
<footer class="big-footer mt-3 pt-3 pb-1 px-5">
|
||||
<div class="d-flex flex-column flex-md-row mb-2">
|
||||
<div class="align-start flex-grow-1">
|
||||
<Logo />
|
||||
<ul class="mt-2 list-unstyled">
|
||||
<li><strong>Version</strong> {meta.version}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="align-end">
|
||||
<ul class="list-unstyled">
|
||||
<li>{meta.users.total} <strong>users</strong></li>
|
||||
<li>{meta.members} <strong>members</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list-inline">
|
||||
<a
|
||||
class="list-inline-item link-underline link-underline-opacity-0"
|
||||
target="_blank"
|
||||
href={meta.repository}
|
||||
>
|
||||
<li class="list-inline-item">
|
||||
<Git />
|
||||
Source code
|
||||
</li>
|
||||
</a>
|
||||
<a
|
||||
class="list-inline-item link-underline link-underline-opacity-0"
|
||||
target="_blank"
|
||||
href="https://status.pronouns.cc"
|
||||
>
|
||||
<li class="list-inline-item">
|
||||
<Reception4 />
|
||||
Status
|
||||
</li>
|
||||
</a>
|
||||
<a class="list-inline-item link-underline link-underline-opacity-0" href="/page/about">
|
||||
<li class="list-inline-item">
|
||||
<Envelope />
|
||||
About and contact
|
||||
</li>
|
||||
</a>
|
||||
<a class="list-inline-item link-underline link-underline-opacity-0" href="/page/tos">
|
||||
<li class="list-inline-item">
|
||||
<CardText />
|
||||
Terms of service
|
||||
</li>
|
||||
</a>
|
||||
<a class="list-inline-item link-underline link-underline-opacity-0" href="/page/privacy">
|
||||
<li class="list-inline-item">
|
||||
<Shield />
|
||||
Privacy policy
|
||||
</li>
|
||||
</a>
|
||||
<a class="list-inline-item link-underline link-underline-opacity-0" href="/page/changelog">
|
||||
<li class="list-inline-item">
|
||||
<Newspaper />
|
||||
Changelog
|
||||
</li>
|
||||
</a>
|
||||
<a class="list-inline-item link-underline link-underline-opacity-0" href="/page/donate">
|
||||
<li class="list-inline-item">
|
||||
<CashCoin />
|
||||
Donate
|
||||
</li>
|
||||
</a>
|
||||
</ul>
|
||||
</footer>
|
|
@ -3,16 +3,11 @@
|
|||
import "../app.scss";
|
||||
import type { LayoutData } from "./$types";
|
||||
import Navbar from "$components/Navbar.svelte";
|
||||
import Footer from "$components/Footer.svelte";
|
||||
|
||||
type Props = { children: Snippet; data: LayoutData };
|
||||
let { children, data }: Props = $props();
|
||||
</script>
|
||||
|
||||
<div class="d-flex flex-column min-vh-100">
|
||||
<div class="flex-grow-1">
|
||||
<Navbar user={data.meUser} meta={data.meta} />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<Footer meta={data.meta} />
|
||||
</div>
|
||||
<Navbar user={data.meUser} meta={data.meta} />
|
||||
|
||||
{@render children?.()}
|
||||
|
|
Loading…
Reference in a new issue