Add per-user active session counts to IAM user list
Move active_sessions field from UserDetailResponse into UserListItem so GET /admin/users returns session counts. Uses a correlated subquery to count non-revoked, non-expired sessions per user. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a128005ae5
commit
9f7bbbfcbb
@ -108,12 +108,34 @@ async def list_users(
|
|||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
_actor: User = Depends(get_current_user),
|
_actor: User = Depends(get_current_user),
|
||||||
):
|
):
|
||||||
"""Return all users with basic stats."""
|
"""Return all users with basic stats including active session counts."""
|
||||||
result = await db.execute(sa.select(User).order_by(User.created_at))
|
active_sub = (
|
||||||
users = result.scalars().all()
|
sa.select(sa.func.count())
|
||||||
|
.select_from(UserSession)
|
||||||
|
.where(
|
||||||
|
UserSession.user_id == User.id,
|
||||||
|
UserSession.revoked == False,
|
||||||
|
UserSession.expires_at > datetime.now(),
|
||||||
|
)
|
||||||
|
.correlate(User)
|
||||||
|
.scalar_subquery()
|
||||||
|
)
|
||||||
|
|
||||||
|
result = await db.execute(
|
||||||
|
sa.select(User, active_sub.label("active_sessions"))
|
||||||
|
.order_by(User.created_at)
|
||||||
|
)
|
||||||
|
rows = result.all()
|
||||||
|
|
||||||
return UserListResponse(
|
return UserListResponse(
|
||||||
users=[UserListItem.model_validate(u) for u in users],
|
users=[
|
||||||
total=len(users),
|
UserListItem(
|
||||||
|
**UserListItem.model_validate(user).model_dump(exclude={"active_sessions"}),
|
||||||
|
active_sessions=count,
|
||||||
|
)
|
||||||
|
for user, count in rows
|
||||||
|
],
|
||||||
|
total=len(rows),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,7 @@ class UserListItem(BaseModel):
|
|||||||
totp_enabled: bool
|
totp_enabled: bool
|
||||||
mfa_enforce_pending: bool
|
mfa_enforce_pending: bool
|
||||||
created_at: datetime
|
created_at: datetime
|
||||||
|
active_sessions: int = 0
|
||||||
|
|
||||||
model_config = ConfigDict(from_attributes=True)
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ class UserListResponse(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class UserDetailResponse(UserListItem):
|
class UserDetailResponse(UserListItem):
|
||||||
active_sessions: int
|
pass
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user