2023-02-18 08:52:17 +01:00
|
|
|
using MongoDB.Entities;
|
|
|
|
|
|
|
|
|
|
using System.ComponentModel.DataAnnotations;
|
|
|
|
|
|
2023-02-19 00:43:43 +01:00
|
|
|
namespace PrivaPub.Models.User
|
2023-02-18 08:52:17 +01:00
|
|
|
{
|
|
|
|
|
public class RootUser : Entity
|
|
|
|
|
{
|
|
|
|
|
[StringLength(32)]
|
|
|
|
|
public string UserName { get; set; }
|
|
|
|
|
[EmailAddress]
|
|
|
|
|
public string Email { get; set; }
|
|
|
|
|
public bool IsEmailValidated { get; set; } = false;
|
|
|
|
|
public bool IsBanned { get; set; } = false;
|
|
|
|
|
public string HashedPassword { get; set; }
|
|
|
|
|
public List<string> Policies { get; set; } = new() { ClientModels.Policies.IsUser };
|
|
|
|
|
public RootUserSettings Settings { get; set; } = new();
|
|
|
|
|
|
|
|
|
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
|
|
|
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
|
|
|
|
public DateTime? DeletedAt { get; set; }
|
2026-10-04 03:48:32 +02:00
|
|
|
public DateTime? CredentialsChangedAt { get; set; }//when RootSessions last ended every session
|
|
|
|
|
public string SessionStamp { get; set; }//carried by every /clientapi token; a new one ends the tokens issued before
|
2026-10-17 03:13:16 +02:00
|
|
|
public List<EndedSession> EndedSessions { get; set; } = new();//sessions signed out one by one, until their tokens expire
|
2026-10-17 03:18:19 +02:00
|
|
|
public RootTotp Totp { get; set; }//two-factor sign-in, when the login set it up (Services/TwoFactor.cs)
|
2026-10-16 23:21:41 +02:00
|
|
|
|
|
|
|
|
/// <summary>An administrator is a moderator too (IsAdminPolicy asks for both); otherwise a plain user.</summary>
|
|
|
|
|
public void SetAdmin(bool admin)
|
|
|
|
|
{
|
|
|
|
|
Policies.RemoveAll(p => p is ClientModels.Policies.IsAdmin or ClientModels.Policies.IsModerator);
|
|
|
|
|
if (admin)
|
|
|
|
|
Policies.AddRange([ClientModels.Policies.IsAdmin, ClientModels.Policies.IsModerator]);
|
|
|
|
|
if (!Policies.Contains(ClientModels.Policies.IsUser))
|
|
|
|
|
Policies.Add(ClientModels.Policies.IsUser);
|
|
|
|
|
UpdatedAt = DateTime.UtcNow;
|
|
|
|
|
}
|
2023-02-18 08:52:17 +01:00
|
|
|
}
|
|
|
|
|
|
2026-10-17 03:18:19 +02:00
|
|
|
// TOTP (RFC 6238: 30 s, 6 digits, SHA-1, as every authenticator app reads it). PendingSecret waits for its first code;
|
|
|
|
|
// LastStep refuses a code used before; a recovery code is kept as its SHA-256 and works once.
|
|
|
|
|
public class RootTotp
|
|
|
|
|
{
|
|
|
|
|
public string Secret { get; set; }//base32
|
|
|
|
|
public DateTime? EnabledAt { get; set; }
|
|
|
|
|
public long LastStep { get; set; }
|
|
|
|
|
public List<string> RecoveryCodeHashes { get; set; } = new();
|
|
|
|
|
public string PendingSecret { get; set; }
|
|
|
|
|
public DateTime? PendingSince { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-17 03:13:16 +02:00
|
|
|
// a session that signed out: its tokens carry Sid, and are refused until Until, when they would have expired anyway
|
|
|
|
|
public class EndedSession
|
|
|
|
|
{
|
|
|
|
|
public string Sid { get; set; }
|
|
|
|
|
public DateTime Until { get; set; }
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-18 08:52:17 +01:00
|
|
|
public class RootUserSettings
|
|
|
|
|
{
|
|
|
|
|
public string LanguageCode { get; set; } = "en-GB";
|
2026-10-17 03:13:16 +02:00
|
|
|
public DateTime? SavedAt { get; set; }//when a client last saved them; until then a client keeps its own
|
2023-02-18 08:52:17 +01:00
|
|
|
|
|
|
|
|
public short IconsThemeIndexColour { get; set; } = 25;
|
|
|
|
|
public short LightThemeIndexColour { get; set; } = 25;
|
|
|
|
|
public short DarkThemeIndexColour { get; set; } = 215;
|
|
|
|
|
public bool PreferSystemTheming { get; set; } = true;
|
|
|
|
|
public bool ThemeIsDarkMode { get; set; } = false;
|
|
|
|
|
public bool ThemeIsDarkGray { get; set; } = false;
|
|
|
|
|
public bool ThemeIsLightGray { get; set; } = true;
|
|
|
|
|
}
|
|
|
|
|
}
|