use crate::errors::{AuthError, AuthResult}; use crate::services::AuthService; use crate::session::{Session, SessionKey, SessionStore}; impl AuthService { /// 把 KenApi 会话键(session cookie 的值)解析成内部 RPC 使用的主体。 pub async fn resolve_internal_session( &self, credential: &str, request_id: &str, ) -> AuthResult { let key = SessionKey::try_from(credential.to_owned()).map_err(|_| AuthError::Unauthenticated)?; let Some((state, _ttl)) = self.sessions.load(&key).await? else { return Err(AuthError::Unauthenticated); }; // Session 内部是 Rc>(非 Send):先同步取完字段再 await。 let (user_id, security_version, auth_session_id) = { let session = Session::from_state(state); ( session.uid().ok_or(AuthError::Unauthenticated)?, session .security_version()? .ok_or(AuthError::Unauthenticated)?, session.session_id().ok_or(AuthError::Unauthenticated)?, ) }; let (user, mfa_verified) = self .accounts .check_session( user_id, security_version, &auth_session_id, Some(request_id), ) .await?; Ok(principal_of( &user, security_version, auth_session_id, mfa_verified, )) } /// 信封身份的权威复核:用户仍有效且安全版本一致。 pub async fn attest_internal_identity( &self, user_id: i64, security_version: i64, _request_id: &str, ) -> AuthResult { if user_id <= 0 || security_version <= 0 { return Err(AuthError::Unauthenticated); } let user = self.accounts.user(user_id).await?; if user.security_version != security_version as i32 { return Err(AuthError::Unauthenticated); } Ok(principal_of( &user, user.security_version, String::new(), false, )) } } fn principal_of( user: &crate::models::users::users::Model, security_version: i32, session_id: String, mfa_verified: bool, ) -> proto::internal::v1::SessionPrincipal { proto::internal::v1::SessionPrincipal { user_id: user.id, session_id, security_version: i64::from(security_version), scopes: vec!["event".to_string()], mfa_verified, expires_at_unix_ms: 0, } }