use db::conn::sea_orm::{EntityTrait, QueryFilter, QueryOrder}; use uuid::Uuid; use crate::error::{UserError, UserResult}; use crate::features::UserService; use jwt::session; use super::types::{ListSessionsQuery, SessionView}; pub async fn list(svc: &UserService, caller: Uuid, q: ListSessionsQuery) -> UserResult> { let db = svc.db.reader(); let mut sel = db::user::user_sessions::Entity::find() .filter(db::user::user_sessions::COLUMN.user_id.eq(caller)) .order_by_desc(db::user::user_sessions::COLUMN.created_at); if let Some(app_id) = q.app_id { sel = sel.filter(db::user::user_sessions::COLUMN.app_id.eq(app_id)); } if !q.include_revoked { sel = sel.filter(db::user::user_sessions::COLUMN.is_revoked.eq(false)); } let rows = sel.all(&db).await?; Ok(rows.into_iter().map(SessionView::from).collect()) } pub async fn revoke_one(svc: &UserService, caller: Uuid, session_id: Uuid) -> UserResult<()> { let writer = svc.db.writer(); let row = db::user::user_sessions::Entity::find_by_id(session_id) .one(&writer) .await? .ok_or_else(|| UserError::NotFound(format!("session {session_id}")))?; if row.user_id != caller { return Err(UserError::Forbidden( "cannot revoke other user's session".into(), )); } session::revoke_session(&writer, session_id) .await .map_err(|e| UserError::Internal(format!("jwt revoke_session: {e}")))?; Ok(()) } pub async fn revoke_all(svc: &UserService, caller: Uuid) -> UserResult { let writer = svc.db.writer(); let result = db::user::user_sessions::Entity::delete_many() .filter(db::user::user_sessions::COLUMN.user_id.eq(caller)) .exec(&writer) .await?; Ok(result.rows_affected) }