[backend/database] Move user_profile columns that only concern local users to user_settings
This commit also removes a bunch of obsolete user_profile columns.
This commit is contained in:
parent
10cc6232f3
commit
09cda1a89e
12 changed files with 533 additions and 320 deletions
|
@ -64,8 +64,6 @@ public class AccountController(
|
|||
user.IsBot = request.IsBot.Value;
|
||||
if (request.IsExplorable.HasValue)
|
||||
user.IsExplorable = request.IsExplorable.Value;
|
||||
if (request.Source?.Sensitive.HasValue ?? false)
|
||||
user.UserProfile.AlwaysMarkNsfw = request.Source.Sensitive.Value;
|
||||
if (request.HideCollections.HasValue)
|
||||
user.UserProfile.FFVisibility = request.HideCollections.Value
|
||||
? UserProfile.UserProfileFFVisibility.Private
|
||||
|
@ -79,6 +77,8 @@ public class AccountController(
|
|||
|
||||
if (request.Source?.Privacy != null)
|
||||
user.UserSettings.DefaultNoteVisibility = StatusEntity.DecodeVisibility(request.Source.Privacy);
|
||||
if (request.Source?.Sensitive.HasValue ?? false)
|
||||
user.UserSettings.AlwaysMarkNsfw = request.Source.Sensitive.Value;
|
||||
|
||||
if (request.Fields?.Where(p => p is { Name: not null, Value: not null }).ToList() is { Count: > 0 } fields)
|
||||
{
|
||||
|
|
|
@ -61,13 +61,13 @@ public class AdminController(
|
|||
[ProducesErrors(HttpStatusCode.BadRequest, HttpStatusCode.NotFound)]
|
||||
public async Task ResetPassword(string id, [FromBody] ResetPasswordRequest request)
|
||||
{
|
||||
var profile = await db.UserProfiles.FirstOrDefaultAsync(p => p.UserId == id && p.UserHost == null) ??
|
||||
var settings = await db.UserSettings.FirstOrDefaultAsync(p => p.UserId == id) ??
|
||||
throw GracefulException.RecordNotFound();
|
||||
|
||||
if (request.Password.Length < 8)
|
||||
throw GracefulException.BadRequest("Password must be at least 8 characters long");
|
||||
|
||||
profile.Password = AuthHelpers.HashPassword(request.Password);
|
||||
settings.Password = AuthHelpers.HashPassword(request.Password);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,10 +54,10 @@ public class AuthController(DatabaseContext db, UserService userSvc, UserRendere
|
|||
p.UsernameLower == request.Username.ToLowerInvariant());
|
||||
if (user == null)
|
||||
throw GracefulException.Forbidden("Invalid username or password");
|
||||
var profile = await db.UserProfiles.FirstOrDefaultAsync(p => p.User == user);
|
||||
if (profile?.Password == null)
|
||||
var settings = await db.UserSettings.FirstOrDefaultAsync(p => p.User == user);
|
||||
if (settings?.Password == null)
|
||||
throw GracefulException.Forbidden("Invalid username or password");
|
||||
if (!AuthHelpers.ComparePassword(request.Password, profile.Password))
|
||||
if (!AuthHelpers.ComparePassword(request.Password, settings.Password))
|
||||
throw GracefulException.Forbidden("Invalid username or password");
|
||||
|
||||
var session = HttpContext.GetSession();
|
||||
|
@ -67,7 +67,7 @@ public class AuthController(DatabaseContext db, UserService userSvc, UserRendere
|
|||
{
|
||||
Id = IdHelpers.GenerateSlowflakeId(),
|
||||
UserId = user.Id,
|
||||
Active = !profile.TwoFactorEnabled,
|
||||
Active = !settings.TwoFactorEnabled,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
Token = CryptographyHelpers.GenerateRandomString(32)
|
||||
};
|
||||
|
@ -109,15 +109,15 @@ public class AuthController(DatabaseContext db, UserService userSvc, UserRendere
|
|||
Justification = "Argon2 is execution time-heavy by design")]
|
||||
public async Task<AuthResponse> ChangePassword([FromBody] ChangePasswordRequest request)
|
||||
{
|
||||
var user = HttpContext.GetUser() ?? throw new GracefulException("HttpContext.GetUser() was null");
|
||||
var userProfile = await db.UserProfiles.FirstOrDefaultAsync(p => p.User == user);
|
||||
if (userProfile is not { Password: not null }) throw new GracefulException("userProfile?.Password was null");
|
||||
if (!AuthHelpers.ComparePassword(request.OldPassword, userProfile.Password))
|
||||
var user = HttpContext.GetUser() ?? throw new GracefulException("HttpContext.GetUser() was null");
|
||||
var settings = await db.UserSettings.FirstOrDefaultAsync(p => p.User == user);
|
||||
if (settings is not { Password: not null }) throw new GracefulException("settings?.Password was null");
|
||||
if (!AuthHelpers.ComparePassword(request.OldPassword, settings.Password))
|
||||
throw GracefulException.BadRequest("old_password is invalid");
|
||||
if (request.NewPassword.Length < 8)
|
||||
throw GracefulException.BadRequest("Password must be at least 8 characters long");
|
||||
|
||||
userProfile.Password = AuthHelpers.HashPassword(request.NewPassword);
|
||||
settings.Password = AuthHelpers.HashPassword(request.NewPassword);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
return await Login(new AuthRequest { Username = user.Username, Password = request.NewPassword });
|
||||
|
|
|
@ -1089,49 +1089,16 @@ public class DatabaseContext(DbContextOptions<DatabaseContext> options)
|
|||
|
||||
modelBuilder.Entity<UserProfile>(entity =>
|
||||
{
|
||||
entity.Property(e => e.AlwaysMarkNsfw).HasDefaultValue(false);
|
||||
entity.Property(e => e.AutoAcceptFollowed).HasDefaultValue(false);
|
||||
entity.Property(e => e.Birthday)
|
||||
.IsFixedLength()
|
||||
.HasComment("The birthday (YYYY-MM-DD) of the User.");
|
||||
entity.Property(e => e.CarefulBot).HasDefaultValue(false);
|
||||
entity.Property(e => e.ClientData)
|
||||
.HasDefaultValueSql("'{}'::jsonb")
|
||||
.HasComment("The client-specific data of the User.");
|
||||
entity.Property(e => e.Description).HasComment("The description (bio) of the User.");
|
||||
entity.Property(e => e.Email).HasComment("The email address of the User.");
|
||||
entity.Property(e => e.EmailNotificationTypes)
|
||||
.HasDefaultValueSql("'[\"follow\", \"receiveFollowRequest\", \"groupInvited\"]'::jsonb");
|
||||
entity.Property(e => e.EmailVerified).HasDefaultValue(false);
|
||||
entity.Property(e => e.EnableWordMute).HasDefaultValue(false);
|
||||
entity.Property(e => e.Fields).HasDefaultValueSql("'[]'::jsonb");
|
||||
entity.Property(e => e.InjectFeaturedNote).HasDefaultValue(true);
|
||||
entity.Property(e => e.Integrations).HasDefaultValueSql("'{}'::jsonb");
|
||||
entity.Property(e => e.Location).HasComment("The location of the User.");
|
||||
entity.Property(e => e.Mentions).HasDefaultValueSql("'[]'::jsonb");
|
||||
entity.Property(e => e.ModerationNote).HasDefaultValueSql("''::character varying");
|
||||
entity.Property(e => e.MutedInstances)
|
||||
.HasDefaultValueSql("'[]'::jsonb")
|
||||
.HasComment("List of instances muted by the user.");
|
||||
entity.Property(e => e.MutedWords).HasDefaultValueSql("'[]'::jsonb");
|
||||
entity.Property(e => e.NoCrawle)
|
||||
.HasDefaultValue(false)
|
||||
.HasComment("Whether reject index by crawler.");
|
||||
entity.Property(e => e.Password)
|
||||
.HasComment("The password hash of the User. It will be null if the origin of the user is local.");
|
||||
entity.Property(e => e.PreventAiLearning).HasDefaultValue(true);
|
||||
entity.Property(e => e.PublicReactions).HasDefaultValue(false);
|
||||
entity.Property(e => e.ReceiveAnnouncementEmail).HasDefaultValue(true);
|
||||
entity.Property(e => e.Room)
|
||||
.HasDefaultValueSql("'{}'::jsonb")
|
||||
.HasComment("The room data of the User.");
|
||||
entity.Property(e => e.SecurityKeysAvailable).HasDefaultValue(false);
|
||||
entity.Property(e => e.TwoFactorEnabled).HasDefaultValue(false);
|
||||
entity.Property(e => e.Url).HasComment("Remote URL of the user.");
|
||||
entity.Property(e => e.UsePasswordLessLogin).HasDefaultValue(false);
|
||||
entity.Property(e => e.UserHost).HasComment("[Denormalized]");
|
||||
entity.Property(e => e.MutingNotificationTypes)
|
||||
.HasDefaultValueSql("'{}'::public.notification_type_enum[]");
|
||||
entity.Property(e => e.FFVisibility)
|
||||
.HasDefaultValue(UserProfile.UserProfileFFVisibility.Public);
|
||||
entity.Property(e => e.MentionsResolved).HasDefaultValue(false);
|
||||
|
@ -1172,6 +1139,12 @@ public class DatabaseContext(DbContextOptions<DatabaseContext> options)
|
|||
entity.Property(e => e.FilterInaccessible).HasDefaultValue(false);
|
||||
entity.Property(e => e.DefaultNoteVisibility).HasDefaultValue(Note.NoteVisibility.Public);
|
||||
entity.Property(e => e.DefaultRenoteVisibility).HasDefaultValue(Note.NoteVisibility.Public);
|
||||
entity.Property(e => e.AlwaysMarkNsfw).HasDefaultValue(false);
|
||||
entity.Property(e => e.AutoAcceptFollowed).HasDefaultValue(false);
|
||||
entity.Property(e => e.Email);
|
||||
entity.Property(e => e.EmailVerified).HasDefaultValue(false);
|
||||
entity.Property(e => e.Password);
|
||||
entity.Property(e => e.TwoFactorEnabled).HasDefaultValue(false);
|
||||
entity.HasOne(e => e.User).WithOne(e => e.UserSettings);
|
||||
});
|
||||
|
||||
|
|
|
@ -4452,18 +4452,6 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("userId");
|
||||
|
||||
b.Property<bool>("AlwaysMarkNsfw")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("alwaysMarkNsfw");
|
||||
|
||||
b.Property<bool>("AutoAcceptFollowed")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("autoAcceptFollowed");
|
||||
|
||||
b.Property<string>("Birthday")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("character(10)")
|
||||
|
@ -4471,56 +4459,12 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
.IsFixedLength()
|
||||
.HasComment("The birthday (YYYY-MM-DD) of the User.");
|
||||
|
||||
b.Property<bool>("CarefulBot")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("carefulBot");
|
||||
|
||||
b.Property<string>("ClientData")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("clientData")
|
||||
.HasDefaultValueSql("'{}'::jsonb")
|
||||
.HasComment("The client-specific data of the User.");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)")
|
||||
.HasColumnName("description")
|
||||
.HasComment("The description (bio) of the User.");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("email")
|
||||
.HasComment("The email address of the User.");
|
||||
|
||||
b.Property<List<string>>("EmailNotificationTypes")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("emailNotificationTypes")
|
||||
.HasDefaultValueSql("'[\"follow\", \"receiveFollowRequest\", \"groupInvited\"]'::jsonb");
|
||||
|
||||
b.Property<bool>("EmailVerified")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("emailVerified");
|
||||
|
||||
b.Property<string>("EmailVerifyCode")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("emailVerifyCode");
|
||||
|
||||
b.Property<bool>("EnableWordMute")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("enableWordMute");
|
||||
|
||||
b.Property<UserProfile.UserProfileFFVisibility>("FFVisibility")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("user_profile_ffvisibility_enum")
|
||||
|
@ -4534,19 +4478,6 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
.HasColumnName("fields")
|
||||
.HasDefaultValueSql("'[]'::jsonb");
|
||||
|
||||
b.Property<bool>("InjectFeaturedNote")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true)
|
||||
.HasColumnName("injectFeaturedNote");
|
||||
|
||||
b.Property<string>("Integrations")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("integrations")
|
||||
.HasDefaultValueSql("'{}'::jsonb");
|
||||
|
||||
b.Property<string>("Lang")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
|
@ -4579,106 +4510,17 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
.HasColumnName("moderationNote")
|
||||
.HasDefaultValueSql("''::character varying");
|
||||
|
||||
b.Property<List<string>>("MutedInstances")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("mutedInstances")
|
||||
.HasDefaultValueSql("'[]'::jsonb")
|
||||
.HasComment("List of instances muted by the user.");
|
||||
|
||||
b.Property<string>("MutedWords")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("mutedWords")
|
||||
.HasDefaultValueSql("'[]'::jsonb");
|
||||
|
||||
b.Property<List<Notification.NotificationType>>("MutingNotificationTypes")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("notification_type_enum[]")
|
||||
.HasColumnName("mutingNotificationTypes")
|
||||
.HasDefaultValueSql("'{}'::public.notification_type_enum[]");
|
||||
|
||||
b.Property<bool>("NoCrawle")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("noCrawle")
|
||||
.HasComment("Whether reject index by crawler.");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("password")
|
||||
.HasComment("The password hash of the User. It will be null if the origin of the user is local.");
|
||||
|
||||
b.Property<string>("PinnedPageId")
|
||||
.HasMaxLength(32)
|
||||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("pinnedPageId");
|
||||
|
||||
b.Property<bool>("PreventAiLearning")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true)
|
||||
.HasColumnName("preventAiLearning");
|
||||
|
||||
b.Property<bool>("PublicReactions")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("publicReactions");
|
||||
|
||||
b.Property<bool>("ReceiveAnnouncementEmail")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true)
|
||||
.HasColumnName("receiveAnnouncementEmail");
|
||||
|
||||
b.Property<string>("Room")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("jsonb")
|
||||
.HasColumnName("room")
|
||||
.HasDefaultValueSql("'{}'::jsonb")
|
||||
.HasComment("The room data of the User.");
|
||||
|
||||
b.Property<bool>("SecurityKeysAvailable")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("securityKeysAvailable");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("twoFactorEnabled");
|
||||
|
||||
b.Property<string>("TwoFactorSecret")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("twoFactorSecret");
|
||||
|
||||
b.Property<string>("TwoFactorTempSecret")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("twoFactorTempSecret");
|
||||
|
||||
b.Property<string>("Url")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
.HasColumnName("url")
|
||||
.HasComment("Remote URL of the user.");
|
||||
|
||||
b.Property<bool>("UsePasswordLessLogin")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("usePasswordLessLogin");
|
||||
|
||||
b.Property<string>("UserHost")
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)")
|
||||
|
@ -4687,8 +4529,6 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.HasIndex("EnableWordMute");
|
||||
|
||||
b.HasIndex("PinnedPageId")
|
||||
.IsUnique();
|
||||
|
||||
|
@ -4771,6 +4611,18 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
.HasColumnType("character varying(32)")
|
||||
.HasColumnName("userId");
|
||||
|
||||
b.Property<bool>("AlwaysMarkNsfw")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("alwaysMarkNsfw");
|
||||
|
||||
b.Property<bool>("AutoAcceptFollowed")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("autoAcceptFollowed");
|
||||
|
||||
b.Property<Note.NoteVisibility>("DefaultNoteVisibility")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("note_visibility_enum")
|
||||
|
@ -4783,18 +4635,50 @@ namespace Iceshrimp.Backend.Core.Database.Migrations
|
|||
.HasDefaultValue(Note.NoteVisibility.Public)
|
||||
.HasColumnName("defaultRenoteVisibility");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("email");
|
||||
|
||||
b.Property<bool>("EmailVerified")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("emailVerified");
|
||||
|
||||
b.Property<bool>("FilterInaccessible")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("filterInaccessible");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("password");
|
||||
|
||||
b.Property<bool>("PrivateMode")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("privateMode");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("twoFactorEnabled");
|
||||
|
||||
b.Property<string>("TwoFactorSecret")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("twoFactorSecret");
|
||||
|
||||
b.Property<string>("TwoFactorTempSecret")
|
||||
.HasMaxLength(128)
|
||||
.HasColumnType("character varying(128)")
|
||||
.HasColumnName("twoFactorTempSecret");
|
||||
|
||||
b.HasKey("UserId");
|
||||
|
||||
b.ToTable("user_settings");
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Iceshrimp.Backend.Core.Database.Tables;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240709231619_RemoveExtraneousUserProfileColumns")]
|
||||
public partial class RemoveExtraneousUserProfileColumns : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_user_profile_enableWordMute",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "carefulBot",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "clientData",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "emailNotificationTypes",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "emailVerifyCode",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "enableWordMute",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "injectFeaturedNote",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "integrations",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "mutedInstances",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "mutedWords",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "mutingNotificationTypes",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "noCrawle",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "preventAiLearning",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "publicReactions",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "receiveAnnouncementEmail",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "room",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "securityKeysAvailable",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "usePasswordLessLogin",
|
||||
table: "user_profile");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "carefulBot",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "clientData",
|
||||
table: "user_profile",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb",
|
||||
comment: "The client-specific data of the User.");
|
||||
|
||||
migrationBuilder.AddColumn<List<string>>(
|
||||
name: "emailNotificationTypes",
|
||||
table: "user_profile",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'[\"follow\", \"receiveFollowRequest\", \"groupInvited\"]'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "emailVerifyCode",
|
||||
table: "user_profile",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "enableWordMute",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "injectFeaturedNote",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "integrations",
|
||||
table: "user_profile",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<List<string>>(
|
||||
name: "mutedInstances",
|
||||
table: "user_profile",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'[]'::jsonb",
|
||||
comment: "List of instances muted by the user.");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "mutedWords",
|
||||
table: "user_profile",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'[]'::jsonb");
|
||||
|
||||
migrationBuilder.AddColumn<List<Notification.NotificationType>>(
|
||||
name: "mutingNotificationTypes",
|
||||
table: "user_profile",
|
||||
type: "notification_type_enum[]",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::public.notification_type_enum[]");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "noCrawle",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false,
|
||||
comment: "Whether reject index by crawler.");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "preventAiLearning",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "publicReactions",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "receiveAnnouncementEmail",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "room",
|
||||
table: "user_profile",
|
||||
type: "jsonb",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'::jsonb",
|
||||
comment: "The room data of the User.");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "securityKeysAvailable",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "usePasswordLessLogin",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_user_profile_enableWordMute",
|
||||
table: "user_profile",
|
||||
column: "enableWordMute");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,202 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Iceshrimp.Backend.Core.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
[DbContext(typeof(DatabaseContext))]
|
||||
[Migration("20240709234348_MoveUserProfilePropsToSettingsStore")]
|
||||
public partial class MoveUserProfilePropsToSettingsStore : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
// First, create user_settings entries for all local users that don't have one yet
|
||||
migrationBuilder.Sql($@"INSERT INTO ""user_settings"" (""userId"") (SELECT ""id"" FROM ""user"" WHERE ""host"" IS NULL) ON CONFLICT DO NOTHING;");
|
||||
|
||||
// Now, create the new columns
|
||||
migrationBuilder.AddColumn<bool>(name: "alwaysMarkNsfw",
|
||||
table: "user_settings",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(name: "autoAcceptFollowed",
|
||||
table: "user_settings",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "email",
|
||||
table: "user_settings",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(name: "emailVerified",
|
||||
table: "user_settings",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "password",
|
||||
table: "user_settings",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(name: "twoFactorEnabled",
|
||||
table: "user_settings",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "twoFactorSecret",
|
||||
table: "user_settings",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "twoFactorTempSecret",
|
||||
table: "user_settings",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
// Then, migrate the settings
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE "user_settings" s
|
||||
SET "alwaysMarkNsfw" = p."alwaysMarkNsfw",
|
||||
"autoAcceptFollowed" = p."autoAcceptFollowed",
|
||||
"email" = p."email",
|
||||
"emailVerified" = p."emailVerified",
|
||||
"twoFactorTempSecret" = p."twoFactorTempSecret",
|
||||
"twoFactorSecret" = p."twoFactorSecret",
|
||||
"twoFactorEnabled" = p."twoFactorEnabled",
|
||||
"password" = p."password"
|
||||
FROM "user_profile" p
|
||||
WHERE p."userId" = s."userId";
|
||||
""");
|
||||
|
||||
// Finally, drop the old columns
|
||||
migrationBuilder.DropColumn(name: "alwaysMarkNsfw",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "autoAcceptFollowed",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "email",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "emailVerified",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "password",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "twoFactorEnabled",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "twoFactorSecret",
|
||||
table: "user_profile");
|
||||
|
||||
migrationBuilder.DropColumn(name: "twoFactorTempSecret",
|
||||
table: "user_profile");
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(name: "alwaysMarkNsfw",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<bool>(name: "autoAcceptFollowed",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "email",
|
||||
table: "user_profile",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true,
|
||||
comment: "The email address of the User.");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(name: "emailVerified",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "password",
|
||||
table: "user_profile",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true,
|
||||
comment: "The password hash of the User. It will be null if the origin of the user is local.");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(name: "twoFactorEnabled",
|
||||
table: "user_profile",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "twoFactorSecret",
|
||||
table: "user_profile",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(name: "twoFactorTempSecret",
|
||||
table: "user_profile",
|
||||
type: "character varying(128)",
|
||||
maxLength: 128,
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE "user_profile" p
|
||||
SET "alwaysMarkNsfw" = s."alwaysMarkNsfw",
|
||||
"autoAcceptFollowed" = s."autoAcceptFollowed",
|
||||
"email" = s."email",
|
||||
"emailVerified" = s."emailVerified",
|
||||
"twoFactorTempSecret" = s."twoFactorTempSecret",
|
||||
"twoFactorSecret" = s."twoFactorSecret",
|
||||
"twoFactorEnabled" = s."twoFactorEnabled",
|
||||
"password" = s."password"
|
||||
FROM "user_settings" s
|
||||
WHERE s."userId" = p."userId";
|
||||
""");
|
||||
|
||||
migrationBuilder.DropColumn(name: "alwaysMarkNsfw",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "autoAcceptFollowed",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "email",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "emailVerified",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "password",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "twoFactorEnabled",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "twoFactorSecret",
|
||||
table: "user_settings");
|
||||
|
||||
migrationBuilder.DropColumn(name: "twoFactorTempSecret",
|
||||
table: "user_settings");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,19 +7,10 @@ using J = System.Text.Json.Serialization.JsonPropertyNameAttribute;
|
|||
namespace Iceshrimp.Backend.Core.Database.Tables;
|
||||
|
||||
[Table("user_profile")]
|
||||
[Index(nameof(EnableWordMute))]
|
||||
[Index(nameof(UserHost))]
|
||||
[Index(nameof(PinnedPageId), IsUnique = true)]
|
||||
public class UserProfile
|
||||
{
|
||||
[PgName("user_profile_ffvisibility_enum")]
|
||||
public enum UserProfileFFVisibility
|
||||
{
|
||||
[PgName("public")] Public,
|
||||
[PgName("followers")] Followers,
|
||||
[PgName("private")] Private
|
||||
}
|
||||
|
||||
[Column("mentionsResolved")] public bool MentionsResolved;
|
||||
|
||||
[Key]
|
||||
|
@ -59,52 +50,6 @@ public class UserProfile
|
|||
|
||||
[Column("ffVisibility")] public UserProfileFFVisibility FFVisibility { get; set; }
|
||||
|
||||
[Column("mutingNotificationTypes")]
|
||||
public List<Notification.NotificationType> MutingNotificationTypes { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The email address of the User.
|
||||
/// </summary>
|
||||
[Column("email")]
|
||||
[StringLength(128)]
|
||||
public string? Email { get; set; }
|
||||
|
||||
[Column("emailVerifyCode")]
|
||||
[StringLength(128)]
|
||||
public string? EmailVerifyCode { get; set; }
|
||||
|
||||
[Column("emailVerified")] public bool EmailVerified { get; set; }
|
||||
|
||||
[Column("twoFactorTempSecret")]
|
||||
[StringLength(128)]
|
||||
public string? TwoFactorTempSecret { get; set; }
|
||||
|
||||
[Column("twoFactorSecret")]
|
||||
[StringLength(128)]
|
||||
public string? TwoFactorSecret { get; set; }
|
||||
|
||||
[Column("twoFactorEnabled")] public bool TwoFactorEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The password hash of the User. It will be null if the origin of the user is local.
|
||||
/// </summary>
|
||||
[Column("password")]
|
||||
[StringLength(128)]
|
||||
public string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The client-specific data of the User.
|
||||
/// </summary>
|
||||
//TODO: refactor this column (it's currently a Dictionary<string, any>, which is terrible)
|
||||
[Column("clientData", TypeName = "jsonb")]
|
||||
public string ClientData { get; set; } = null!;
|
||||
|
||||
[Column("autoAcceptFollowed")] public bool AutoAcceptFollowed { get; set; }
|
||||
|
||||
[Column("alwaysMarkNsfw")] public bool AlwaysMarkNsfw { get; set; }
|
||||
|
||||
[Column("carefulBot")] public bool CarefulBot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// [Denormalized]
|
||||
/// </summary>
|
||||
|
@ -112,62 +57,16 @@ public class UserProfile
|
|||
[StringLength(512)]
|
||||
public string? UserHost { get; set; }
|
||||
|
||||
[Column("securityKeysAvailable")] public bool SecurityKeysAvailable { get; set; }
|
||||
|
||||
[Column("usePasswordLessLogin")] public bool UsePasswordLessLogin { get; set; }
|
||||
|
||||
[Column("pinnedPageId")]
|
||||
[StringLength(32)]
|
||||
public string? PinnedPageId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The room data of the User.
|
||||
/// </summary>
|
||||
//TODO: refactor this column (it's currently a Dictionary<string, any>, which is terrible)
|
||||
[Column("room", TypeName = "jsonb")]
|
||||
public string Room { get; set; } = null!;
|
||||
|
||||
//TODO: refactor this column (it's currently a Dictionary<string, any>, which is terrible)
|
||||
[Column("integrations", TypeName = "jsonb")]
|
||||
public string Integrations { get; set; } = null!;
|
||||
|
||||
[Column("injectFeaturedNote")] public bool InjectFeaturedNote { get; set; }
|
||||
|
||||
[Column("enableWordMute")] public bool EnableWordMute { get; set; }
|
||||
|
||||
//TODO: refactor this column (it's currently a List<string | string[]>, which is terrible)
|
||||
[Column("mutedWords", TypeName = "jsonb")]
|
||||
public string MutedWords { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether reject index by crawler.
|
||||
/// </summary>
|
||||
[Column("noCrawle")]
|
||||
public bool NoCrawle { get; set; }
|
||||
|
||||
[Column("receiveAnnouncementEmail")] public bool ReceiveAnnouncementEmail { get; set; }
|
||||
|
||||
//TODO: refactor this column (this should have been NotificationTypeEnum[])
|
||||
[Column("emailNotificationTypes", TypeName = "jsonb")]
|
||||
public List<string> EmailNotificationTypes { get; set; } = null!;
|
||||
|
||||
[Column("lang")] [StringLength(32)] public string? Lang { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of instances muted by the user.
|
||||
/// </summary>
|
||||
//TODO: refactor this column (this should have been a varchar[])
|
||||
[Column("mutedInstances", TypeName = "jsonb")]
|
||||
public List<string> MutedInstances { get; set; } = null!;
|
||||
|
||||
[Column("publicReactions")] public bool PublicReactions { get; set; }
|
||||
|
||||
[Column("moderationNote")]
|
||||
[StringLength(8192)]
|
||||
public string ModerationNote { get; set; } = null!;
|
||||
|
||||
[Column("preventAiLearning")] public bool PreventAiLearning { get; set; }
|
||||
|
||||
[Column("mentions", TypeName = "jsonb")]
|
||||
public List<Note.MentionedUser> Mentions { get; set; } = null!;
|
||||
|
||||
|
@ -185,4 +84,12 @@ public class UserProfile
|
|||
[J("value")] public required string Value { get; set; }
|
||||
[J("verified")] public bool? IsVerified { get; set; }
|
||||
}
|
||||
|
||||
[PgName("user_profile_ffvisibility_enum")]
|
||||
public enum UserProfileFFVisibility
|
||||
{
|
||||
[PgName("public")] Public = 0,
|
||||
[PgName("followers")] Followers = 1,
|
||||
[PgName("private")] Private = 2
|
||||
}
|
||||
}
|
|
@ -19,4 +19,32 @@ public class UserSettings
|
|||
[Column("defaultRenoteVisibility")] public Note.NoteVisibility DefaultRenoteVisibility { get; set; }
|
||||
[Column("privateMode")] public bool PrivateMode { get; set; }
|
||||
[Column("filterInaccessible")] public bool FilterInaccessible { get; set; }
|
||||
[Column("autoAcceptFollowed")] public bool AutoAcceptFollowed { get; set; }
|
||||
[Column("alwaysMarkNsfw")] public bool AlwaysMarkNsfw { get; set; }
|
||||
|
||||
// @formatter:off
|
||||
|
||||
[Column("email")]
|
||||
[StringLength(128)]
|
||||
public string? Email { get; set; }
|
||||
|
||||
[Column("emailVerified")]
|
||||
public bool EmailVerified { get; set; }
|
||||
|
||||
[Column("twoFactorTempSecret")]
|
||||
[StringLength(128)]
|
||||
public string? TwoFactorTempSecret { get; set; }
|
||||
|
||||
[Column("twoFactorSecret")]
|
||||
[StringLength(128)]
|
||||
public string? TwoFactorSecret { get; set; }
|
||||
|
||||
[Column("twoFactorEnabled")]
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
|
||||
[Column("password")]
|
||||
[StringLength(128)]
|
||||
public string? Password { get; set; }
|
||||
|
||||
// @formatter:on
|
||||
}
|
|
@ -90,16 +90,11 @@ public class SystemUserService(ILogger<SystemUserService> logger, DatabaseContex
|
|||
PublicKey = keypair.ExportSubjectPublicKeyInfoPem()
|
||||
};
|
||||
|
||||
var userProfile = new UserProfile
|
||||
{
|
||||
UserId = user.Id,
|
||||
AutoAcceptFollowed = false,
|
||||
Password = null
|
||||
};
|
||||
|
||||
var userProfile = new UserProfile { UserId = user.Id };
|
||||
var userSettings = new UserSettings { UserId = user.Id, Password = null };
|
||||
var usedUsername = new UsedUsername { CreatedAt = DateTime.UtcNow, Username = username.ToLowerInvariant() };
|
||||
|
||||
await db.AddRangeAsync(user, userKeypair, userProfile, usedUsername);
|
||||
await db.AddRangeAsync(user, userKeypair, userProfile, userSettings, usedUsername);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
return user;
|
||||
|
|
|
@ -399,7 +399,8 @@ public class UserService(
|
|||
PublicKey = keypair.ExportSubjectPublicKeyInfoPem()
|
||||
};
|
||||
|
||||
var userProfile = new UserProfile { UserId = user.Id, Password = AuthHelpers.HashPassword(password) };
|
||||
var userProfile = new UserProfile { UserId = user.Id };
|
||||
var userSettings = new UserSettings { UserId = user.Id, Password = AuthHelpers.HashPassword(password) };
|
||||
|
||||
var usedUsername = new UsedUsername { CreatedAt = DateTime.UtcNow, Username = username.ToLowerInvariant() };
|
||||
|
||||
|
@ -411,7 +412,7 @@ public class UserService(
|
|||
db.Remove(ticket);
|
||||
}
|
||||
|
||||
await db.AddRangeAsync(user, userKeypair, userProfile, usedUsername);
|
||||
await db.AddRangeAsync(user, userKeypair, userProfile, userSettings, usedUsername);
|
||||
await db.SaveChangesAsync();
|
||||
|
||||
return user;
|
||||
|
|
|
@ -55,10 +55,10 @@ public class AuthorizeModel(DatabaseContext db) : PageModel
|
|||
p.UsernameLower == username.ToLowerInvariant());
|
||||
if (user == null)
|
||||
throw GracefulException.Forbidden("Invalid username or password");
|
||||
var userProfile = await db.UserProfiles.FirstOrDefaultAsync(p => p.User == user);
|
||||
if (userProfile?.Password == null)
|
||||
var userSettings = await db.UserSettings.FirstOrDefaultAsync(p => p.User == user);
|
||||
if (userSettings?.Password == null)
|
||||
throw GracefulException.Forbidden("Invalid username or password");
|
||||
if (AuthHelpers.ComparePassword(password, userProfile.Password) == false)
|
||||
if (AuthHelpers.ComparePassword(password, userSettings.Password) == false)
|
||||
throw GracefulException.Forbidden("Invalid username or password");
|
||||
|
||||
var token = new OauthToken
|
||||
|
|
Loading…
Add table
Reference in a new issue