♻️ Move most of models to the Shared package

This commit is contained in:
2025-07-06 22:34:52 +08:00
parent cb4acbb3fc
commit 65450e8511
170 changed files with 679 additions and 101121 deletions

View File

@ -12,6 +12,7 @@ using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using NodaTime;
using System.Text;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Auth.OidcProvider.Controllers;
using DysonNetwork.Sphere.Auth.OidcProvider.Services;
using SystemClock = NodaTime.SystemClock;

View File

@ -6,6 +6,7 @@ using NodaTime;
using Microsoft.EntityFrameworkCore;
using System.IdentityModel.Tokens.Jwt;
using System.Text.Json;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Connection;
namespace DysonNetwork.Sphere.Auth;

View File

@ -5,6 +5,9 @@ using DysonNetwork.Sphere.Account;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using System.Text.Json;
using DysonNetwork.Shared.Models;
using Challenge = DysonNetwork.Sphere.Auth.Proto.Challenge;
using Session = DysonNetwork.Sphere.Auth.Proto.Session;
namespace DysonNetwork.Sphere.Auth;

View File

@ -1,5 +1,6 @@
using System.Security.Cryptography;
using System.Text.Json;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Account;
using DysonNetwork.Sphere.Storage;
using Microsoft.EntityFrameworkCore;
@ -24,7 +25,7 @@ public class AuthService(
/// <param name="request">The request context</param>
/// <param name="account">The account to login</param>
/// <returns>The required steps to login</returns>
public async Task<int> DetectChallengeRisk(HttpRequest request, Account.Account account)
public async Task<int> DetectChallengeRisk(HttpRequest request, Shared.Models.Account account)
{
// 1) Find out how many authentication factors the account has enabled.
var maxSteps = await db.AccountAuthFactors
@ -73,7 +74,7 @@ public class AuthService(
return totalRequiredSteps;
}
public async Task<Session> CreateSessionForOidcAsync(Account.Account account, Instant time, Guid? customAppId = null)
public async Task<Session> CreateSessionForOidcAsync(Shared.Models.Account account, Instant time, Guid? customAppId = null)
{
var challenge = new Challenge
{

View File

@ -1,4 +1,5 @@
using System.Security.Cryptography;
using DysonNetwork.Shared.Models;
namespace DysonNetwork.Sphere.Auth;

View File

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Account;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
@ -114,7 +115,7 @@ public class OidcProviderController(
[Authorize]
public async Task<IActionResult> GetUserInfo()
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser ||
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser ||
HttpContext.Items["CurrentSession"] is not Session currentSession) return Unauthorized();
// Get requested scopes from the token

View File

@ -2,6 +2,7 @@ using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Auth.OidcProvider.Models;
using DysonNetwork.Sphere.Auth.OidcProvider.Options;
using DysonNetwork.Sphere.Auth.OidcProvider.Responses;

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Account;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@ -25,7 +26,7 @@ public class ConnectionController(
[HttpGet]
public async Task<ActionResult<List<AccountConnection>>> GetConnections()
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser)
return Unauthorized();
var connections = await db.AccountConnections
@ -48,7 +49,7 @@ public class ConnectionController(
[HttpDelete("{id:guid}")]
public async Task<ActionResult> RemoveConnection(Guid id)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser)
return Unauthorized();
var connection = await db.AccountConnections
@ -66,7 +67,7 @@ public class ConnectionController(
[HttpPost("/auth/connect/apple/mobile")]
public async Task<ActionResult> ConnectAppleMobile([FromBody] AppleMobileConnectRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser)
return Unauthorized();
if (GetOidcService("apple") is not AppleOidcService appleService)
@ -132,7 +133,7 @@ public class ConnectionController(
[HttpPost("connect")]
public async Task<ActionResult<object>> InitiateConnection([FromBody] ConnectProviderRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser)
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser)
return Unauthorized();
var oidcService = GetOidcService(request.Provider);

View File

@ -1,3 +1,4 @@
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Account;
using DysonNetwork.Sphere.Storage;
using Microsoft.AspNetCore.Mvc;
@ -32,7 +33,7 @@ public class OidcController(
var oidcService = GetOidcService(provider);
// If the user is already authenticated, treat as an account connection request
if (HttpContext.Items["CurrentUser"] is Account.Account currentUser)
if (HttpContext.Items["CurrentUser"] is Shared.Models.Account currentUser)
{
var state = Guid.NewGuid().ToString();
var nonce = Guid.NewGuid().ToString();
@ -125,7 +126,7 @@ public class OidcController(
};
}
private async Task<Account.Account> FindOrCreateAccount(OidcUserInfo userInfo, string provider)
private async Task<Shared.Models.Account> FindOrCreateAccount(OidcUserInfo userInfo, string provider)
{
if (string.IsNullOrEmpty(userInfo.Email))
throw new ArgumentException("Email is required for account creation");

View File

@ -1,6 +1,7 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Shared.Models;
using DysonNetwork.Sphere.Account;
using DysonNetwork.Sphere.Storage;
using Microsoft.EntityFrameworkCore;
@ -190,7 +191,7 @@ public abstract class OidcService(
/// </summary>
public async Task<Challenge> CreateChallengeForUserAsync(
OidcUserInfo userInfo,
Account.Account account,
Shared.Models.Account account,
HttpContext request,
string deviceId
)

View File

@ -1,69 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Sphere.Developer;
using NodaTime;
using Point = NetTopologySuite.Geometries.Point;
namespace DysonNetwork.Sphere.Auth;
public class Session : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(1024)] public string? Label { get; set; }
public Instant? LastGrantedAt { get; set; }
public Instant? ExpiredAt { get; set; }
public Guid AccountId { get; set; }
[JsonIgnore] public Account.Account Account { get; set; } = null!;
public Guid ChallengeId { get; set; }
public Challenge Challenge { get; set; } = null!;
public Guid? AppId { get; set; }
public CustomApp? App { get; set; }
}
public enum ChallengeType
{
Login,
OAuth, // Trying to authorize other platforms
Oidc // Trying to connect other platforms
}
public enum ChallengePlatform
{
Unidentified,
Web,
Ios,
Android,
MacOs,
Windows,
Linux
}
public class Challenge : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
public Instant? ExpiredAt { get; set; }
public int StepRemain { get; set; }
public int StepTotal { get; set; }
public int FailedAttempts { get; set; }
public ChallengePlatform Platform { get; set; } = ChallengePlatform.Unidentified;
public ChallengeType Type { get; set; } = ChallengeType.Login;
[Column(TypeName = "jsonb")] public List<Guid> BlacklistFactors { get; set; } = new();
[Column(TypeName = "jsonb")] public List<string> Audiences { get; set; } = new();
[Column(TypeName = "jsonb")] public List<string> Scopes { get; set; } = new();
[MaxLength(128)] public string? IpAddress { get; set; }
[MaxLength(512)] public string? UserAgent { get; set; }
[MaxLength(256)] public string? DeviceId { get; set; }
[MaxLength(1024)] public string? Nonce { get; set; }
public Point? Location { get; set; }
public Guid AccountId { get; set; }
[JsonIgnore] public Account.Account Account { get; set; } = null!;
public Challenge Normalize()
{
if (StepRemain == 0 && BlacklistFactors.Count == 0) StepRemain = StepTotal;
return this;
}
}