♻️ Updated auth challenges and device API to fit new design

This commit is contained in:
2025-12-03 22:43:35 +08:00
parent 4faa1a4b64
commit 4a71f92ef0
3 changed files with 52 additions and 23 deletions

View File

@@ -560,7 +560,7 @@ public class AccountCurrentController(
[HttpGet("devices")] [HttpGet("devices")]
[Authorize] [Authorize]
public async Task<ActionResult<List<SnAuthClientWithChallenge>>> GetDevices() public async Task<ActionResult<List<SnAuthClientWithSessions>>> GetDevices()
{ {
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser || if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser ||
HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized(); HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized();
@@ -571,18 +571,41 @@ public class AccountCurrentController(
.Where(device => device.AccountId == currentUser.Id) .Where(device => device.AccountId == currentUser.Id)
.ToListAsync(); .ToListAsync();
var challengeDevices = devices.Select(SnAuthClientWithChallenge.FromClient).ToList(); var sessionDevices = devices.Select(SnAuthClientWithSessions.FromClient).ToList();
var deviceIds = challengeDevices.Select(x => x.DeviceId).ToList(); var clientIds = sessionDevices.Select(x => x.Id).ToList();
var authChallenges = await db.AuthChallenges var authSessions = await db.AuthSessions
.Where(c => deviceIds.Contains(c.DeviceId)) .Where(c => clientIds.Contains(c.Id))
.GroupBy(c => c.DeviceId) .GroupBy(c => c.Id)
.ToDictionaryAsync(c => c.Key, c => c.ToList()); .ToDictionaryAsync(c => c.Key, c => c.ToList());
foreach (var challengeDevice in challengeDevices) foreach (var dev in sessionDevices)
if (authChallenges.TryGetValue(challengeDevice.DeviceId, out var challenge)) if (authSessions.TryGetValue(dev.Id, out var challenge))
challengeDevice.Challenges = challenge; dev.Sessions = challenge;
return Ok(challengeDevices); return Ok(sessionDevices);
}
[HttpGet("challenges")]
[Authorize]
public async Task<ActionResult<List<SnAuthChallenge>>> GetChallenges(
[FromQuery] int take = 20,
[FromQuery] int offset = 0
)
{
if (HttpContext.Items["CurrentUser"] is not SnAccount currentUser) return Unauthorized();
var query = db.AuthChallenges
.Where(challenge => challenge.AccountId == currentUser.Id)
.OrderByDescending(c => c.CreatedAt);
var total = await query.CountAsync();
Response.Headers.Append("X-Total", total.ToString());
var challenges = await query
.Skip(offset)
.Take(take)
.ToListAsync();
return Ok(challenges);
} }
[HttpGet("sessions")] [HttpGet("sessions")]
@@ -596,6 +619,7 @@ public class AccountCurrentController(
HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized(); HttpContext.Items["CurrentSession"] is not SnAuthSession currentSession) return Unauthorized();
var query = db.AuthSessions var query = db.AuthSessions
.OrderByDescending(x => x.LastGrantedAt)
.Include(session => session.Account) .Include(session => session.Account)
.Where(session => session.Account.Id == currentUser.Id); .Where(session => session.Account.Id == currentUser.Id);
@@ -604,7 +628,6 @@ public class AccountCurrentController(
Response.Headers.Append("X-Auth-Session", currentSession.Id.ToString()); Response.Headers.Append("X-Auth-Session", currentSession.Id.ToString());
var sessions = await query var sessions = await query
.OrderByDescending(x => x.LastGrantedAt)
.Skip(offset) .Skip(offset)
.Take(take) .Take(take)
.ToListAsync(); .ToListAsync();

View File

@@ -48,7 +48,8 @@ public class AuthService(
.Take(10) .Take(10)
.ToListAsync(); .ToListAsync();
var recentChallengeIds = recentSessions.Where(s => s.ChallengeId != null).Select(s => s.ChallengeId.Value).ToList(); var recentChallengeIds =
recentSessions.Where(s => s.ChallengeId != null).Select(s => s.ChallengeId.Value).ToList();
var recentChallenges = await db.AuthChallenges.Where(c => recentChallengeIds.Contains(c.Id)).ToListAsync(); var recentChallenges = await db.AuthChallenges.Where(c => recentChallengeIds.Contains(c.Id)).ToListAsync();
var ipAddress = request.HttpContext.Connection.RemoteIpAddress?.ToString(); var ipAddress = request.HttpContext.Connection.RemoteIpAddress?.ToString();
@@ -409,8 +410,12 @@ public class AuthService(
if (challenge.StepRemain != 0) if (challenge.StepRemain != 0)
throw new ArgumentException("Challenge not yet completed."); throw new ArgumentException("Challenge not yet completed.");
var device = await GetOrCreateDeviceAsync(challenge.AccountId, challenge.DeviceId, challenge.DeviceName, var device = await GetOrCreateDeviceAsync(
challenge.Platform); challenge.AccountId,
challenge.DeviceId,
challenge.DeviceName,
challenge.Platform
);
var now = SystemClock.Instance.GetCurrentInstant(); var now = SystemClock.Instance.GetCurrentInstant();
var session = new SnAuthSession var session = new SnAuthSession
@@ -537,7 +542,8 @@ public class AuthService(
return key; return key;
} }
public async Task<SnApiKey> CreateApiKey(Guid accountId, string label, Instant? expiredAt = null, SnAuthSession? parentSession = null) public async Task<SnApiKey> CreateApiKey(Guid accountId, string label, Instant? expiredAt = null,
SnAuthSession? parentSession = null)
{ {
var key = new SnApiKey var key = new SnApiKey
{ {

View File

@@ -153,13 +153,13 @@ public class SnAuthClient : ModelBase
}; };
} }
public class SnAuthClientWithChallenge : SnAuthClient public class SnAuthClientWithSessions : SnAuthClient
{ {
public List<SnAuthChallenge> Challenges { get; set; } = []; public List<SnAuthSession> Sessions { get; set; } = [];
public static SnAuthClientWithChallenge FromClient(SnAuthClient client) public static SnAuthClientWithSessions FromClient(SnAuthClient client)
{ {
return new SnAuthClientWithChallenge return new SnAuthClientWithSessions
{ {
Id = client.Id, Id = client.Id,
Platform = client.Platform, Platform = client.Platform,