:drunk: AI trying to fix bugs

This commit is contained in:
2025-07-06 21:15:30 +08:00
parent 3391c08c04
commit 7d1f096e87
70 changed files with 681 additions and 66945 deletions

View File

@ -7,6 +7,15 @@ using OtpNet;
namespace DysonNetwork.Common.Models;
public enum AccountStatus
{
PendingActivation,
Active,
Suspended,
Banned,
Deleted
}
[Index(nameof(Name), IsUnique = true)]
public class Account : ModelBase
{
@ -30,6 +39,47 @@ public class Account : ModelBase
[JsonIgnore] public ICollection<Relationship> IncomingRelationships { get; set; } = new List<Relationship>();
[JsonIgnore] public ICollection<Subscription> Subscriptions { get; set; } = new List<Subscription>();
public AccountStatus Status { get; set; } = AccountStatus.PendingActivation;
[NotMapped]
public string? Email => GetPrimaryEmail();
public string? GetPrimaryEmail()
{
return Contacts
.FirstOrDefault(c => c.Type == AccountContactType.Email && c.IsPrimary)
?.Content;
}
public void SetPrimaryEmail(string email)
{
// Remove primary flag from existing primary email if any
foreach (var contact in Contacts.Where(c => c.Type == AccountContactType.Email && c.IsPrimary))
{
contact.IsPrimary = false;
}
// Find or create the email contact
var emailContact = Contacts.FirstOrDefault(c =>
c.Type == AccountContactType.Email &&
string.Equals(c.Content, email, StringComparison.OrdinalIgnoreCase));
if (emailContact == null)
{
emailContact = new AccountContact
{
Type = AccountContactType.Email,
Content = email,
IsPrimary = true
};
Contacts.Add(emailContact);
}
else
{
emailContact.IsPrimary = true;
}
}
}
public abstract class Leveling
@ -128,11 +178,28 @@ public class AccountAuthFactor : ModelBase
/// </summary>
public int Trustworthy { get; set; } = 1;
[MaxLength(100)]
public string Name { get; set; } = string.Empty;
[MaxLength(500)]
public string? Description { get; set; }
public bool IsDefault { get; set; }
public bool IsBackup { get; set; }
public Instant? LastUsedAt { get; set; }
public Instant? EnabledAt { get; set; }
public Instant? ExpiredAt { get; set; }
public Instant? DisabledAt { get; set; }
[Column(TypeName = "jsonb")]
public Dictionary<string, object>? Metadata { get; set; }
public Guid AccountId { get; set; }
[JsonIgnore] public Account Account { get; set; } = null!;
// Navigation property for related AuthSessions
[JsonIgnore]
public virtual ICollection<AuthSession>? Sessions { get; set; }
public AccountAuthFactor HashSecret(int cost = 12)
{
@ -174,20 +241,5 @@ public enum AccountAuthFactorType
EmailCode,
InAppCode,
TimedCode,
PinCode,
}
public class AccountConnection : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(4096)] public string Provider { get; set; } = null!;
[MaxLength(8192)] public string ProvidedIdentifier { get; set; } = null!;
[Column(TypeName = "jsonb")] public Dictionary<string, object>? Meta { get; set; } = new();
[JsonIgnore] [MaxLength(4096)] public string? AccessToken { get; set; }
[JsonIgnore] [MaxLength(4096)] public string? RefreshToken { get; set; }
public Instant? LastUsedAt { get; set; }
public Guid AccountId { get; set; }
public Account Account { get; set; } = null!;
PinCode
}

View File

@ -1,6 +1,8 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
using System.Text.Json.Serialization;
using NodaTime;
namespace DysonNetwork.Common.Models;
@ -8,15 +10,8 @@ namespace DysonNetwork.Common.Models;
/// <summary>
/// Represents a connection between an account and an authentication provider
/// </summary>
public class AccountConnection
public class AccountConnection : ModelBase
{
/// <summary>
/// Unique identifier for the connection
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; } = null!;
/// <summary>
/// The account ID this connection is associated with
/// </summary>
@ -36,6 +31,16 @@ public class AccountConnection
[MaxLength(256)]
public string ProvidedIdentifier { get; set; } = null!;
/// <summary>
/// Alias for ProvidedIdentifier for backward compatibility
/// </summary>
[NotMapped]
public string ProviderId
{
get => ProvidedIdentifier;
set => ProvidedIdentifier = value;
}
/// <summary>
/// Display name for the connection
/// </summary>
@ -57,6 +62,27 @@ public class AccountConnection
/// </summary>
public Instant? ExpiresAt { get; set; }
/// <summary>
/// Raw profile data from the provider
/// </summary>
[Column(TypeName = "jsonb")]
public JsonDocument? ProfileData { get; set; }
/// <summary>
/// When the connection was first established
/// </summary>
public Instant ConnectedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
/// <summary>
/// Additional metadata about the connection
/// </summary>
[Column(TypeName = "jsonb")]
public JsonDocument? Metadata { get; set; }
/// <summary>
/// Gets a value indicating whether the connection is currently active
/// </summary>
[NotMapped]
/// <summary>
/// When the connection was first established
/// </summary>
@ -67,15 +93,33 @@ public class AccountConnection
/// </summary>
public Instant? LastUsedAt { get; set; }
/// <summary>
/// Additional metadata about the connection
/// </summary>
[Column(TypeName = "jsonb")]
public Dictionary<string, object>? Meta { get; set; }
/// <summary>
/// Navigation property for the associated account
/// </summary>
[ForeignKey(nameof(AccountId))]
[JsonIgnore]
public virtual Account? Account { get; set; }
/// <summary>
/// Updates the connection's tokens and related metadata
/// </summary>
/// <param name="accessToken">The new access token</param>
/// <param name="refreshToken">The new refresh token, if any</param>
/// <param name="expiresAt">When the access token expires, if any</param>
public void UpdateTokens(string? accessToken, string? refreshToken, Instant? expiresAt)
{
AccessToken = accessToken;
if (!string.IsNullOrEmpty(refreshToken))
{
RefreshToken = refreshToken;
}
if (expiresAt.HasValue)
{
ExpiresAt = expiresAt;
}
LastUsedAt = SystemClock.Instance.GetCurrentInstant();
}
}

View File

@ -0,0 +1,47 @@
namespace DysonNetwork.Common.Models.Auth;
/// <summary>
/// Represents the different types of authentication factors that can be used for multi-factor authentication.
/// </summary>
public enum AuthFactorType
{
/// <summary>
/// Password-based authentication factor.
/// </summary>
Password = 0,
/// <summary>
/// Time-based One-Time Password (TOTP) authentication factor.
/// </summary>
Totp = 1,
/// <summary>
/// Email-based authentication factor.
/// </summary>
Email = 2,
/// <summary>
/// Phone/SMS-based authentication factor.
/// </summary>
Phone = 3,
/// <summary>
/// Security key (FIDO2/WebAuthn) authentication factor.
/// </summary>
SecurityKey = 4,
/// <summary>
/// Recovery code authentication factor.
/// </summary>
RecoveryCode = 5,
/// <summary>
/// Backup code authentication factor.
/// </summary>
BackupCode = 6,
/// <summary>
/// OpenID Connect (OIDC) authentication factor.
/// </summary>
Oidc = 7
}

View File

@ -45,30 +45,3 @@ public enum AuthChallengePlatform
System = 100,
Unknown = 999
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum AuthFactorType
{
Password = 0,
EmailCode = 1,
PhoneCode = 2,
Totp = 3,
WebAuthn = 4,
RecoveryCode = 5,
// Social and federation
Google = 10,
Apple = 11,
Microsoft = 12,
Facebook = 13,
Twitter = 14,
Github = 15,
// Enterprise
Saml = 50,
Oidc = 51,
Ldap = 52,
// Custom factor types
Custom = 100
}

View File

@ -1,10 +1,33 @@
using System.ComponentModel.DataAnnotations;
using NodaTime;
namespace DysonNetwork.Common.Models;
/// <summary>
/// Base class for all entity models in the system.
/// Provides common properties and functionality for tracking entity lifecycle.
/// </summary>
public abstract class ModelBase
{
public Instant CreatedAt { get; set; }
public Instant UpdatedAt { get; set; }
/// <summary>
/// Gets or sets the unique identifier for the entity.
/// </summary>
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// Gets or sets the date and time when the entity was created, in UTC.
/// </summary>
public Instant CreatedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
/// <summary>
/// Gets or sets the date and time when the entity was last updated, in UTC.
/// </summary>
public Instant UpdatedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
/// <summary>
/// Gets or sets the date and time when the entity was soft-deleted, in UTC.
/// Null if the entity has not been deleted.
/// </summary>
public Instant? DeletedAt { get; set; }
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Nodes;
namespace DysonNetwork.Common.Models;