fediverse_personal_access_token.rs
80 lignes · 2931 octets
//! SeaORM entity for `fediverse_personal_access_tokens` (RFC 0030). //! //! Personal access tokens issued by the local instance to remote //! ActivityPub identities. Companion of the core //! [`personal_access_token`](rustwarden_core::models::personal_access_token) //! but scoped to `remote_identities` instead of `users`. //! //! # Storage //! //! Only the SHA-256 hex digest of the plaintext token is persisted in //! `token_hash` — the plaintext is returned once from //! [`crate::services::remote_personal_access_token_service::RemotePersonalAccessTokenService::create`] //! and never stored. //! //! # Token format //! //! Tokens emitted by this service are prefixed `rwfed_pat_` followed by //! 64 hex characters (32 bytes of entropy). The prefix lets the //! consumer disambiguate remote PATs from framework PATs (`rw_pat_…`) //! when both populations can present a token on the same endpoint. use chrono::{DateTime, Utc}; use sea_orm::entity::prelude::*; use serde::{Deserialize, Serialize}; use uuid::Uuid; /// Persistent record of one remote-identity-owned PAT. #[derive(Clone, Debug, Serialize, Deserialize, DeriveEntityModel)] #[sea_orm(table_name = "fediverse_personal_access_tokens")] pub struct Model { /// Stable PK. #[sea_orm(primary_key, auto_increment = false)] pub id: Uuid, /// FK to `remote_identities.id` (owner). pub remote_identity_id: Uuid, /// User-chosen label (max 64 chars, validated at service layer). pub name: String, /// SHA-256 hex digest of the plaintext token (64 chars). #[sea_orm(unique)] pub token_hash: String, /// Requested scopes (consumer vocabulary via /// [`rustwarden_core::services::personal_token_service::TokenScope`]). pub scopes: Vec<String>, /// Optional expiration. `None` = permanent token. #[sea_orm(nullable)] pub expires_at: Option<DateTime<Utc>>, /// Last successful `verify()` (UX). #[sea_orm(nullable)] pub last_used_at: Option<DateTime<Utc>>, /// Creation timestamp. pub created_at: DateTime<Utc>, /// Soft-revocation timestamp. A revoked token is kept for audit but /// refuses authentication. #[sea_orm(nullable)] pub revoked_at: Option<DateTime<Utc>>, } /// SeaORM relations (none modelled here — cross-table FK to /// `remote_identities` is enforced by the migration). #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} impl Model { /// Returns true if `expires_at` is set and in the past. pub fn is_expired(&self) -> bool { self.expires_at.is_some_and(|t| Utc::now() > t) } /// Returns true if `revoked_at` is set. pub fn is_revoked(&self) -> bool { self.revoked_at.is_some() } /// Returns true if the token is neither revoked nor expired. pub fn is_active(&self) -> bool { !self.is_revoked() && !self.is_expired() } }
GitRust