feat: auth hardening + codebase quality sweep
Refresh tokens: RefreshToken entity, PostgresRefreshTokenRepository, login returns refresh token, POST /auth/refresh (rotation), POST /auth/logout, JWT expiry 24h→1h, configurable via with_expiry(). Route protection: require_auth middleware on protected routes, public routes split (register, login, refresh, sharing/access). Authorization: caller_id added to ReadAssetFileQuery, ReadDerivativeQuery, GetStackQuery, DeleteStackCommand with ownership checks. Admin-only gates on processing, storage, sidecar, duplicates handlers. Quality fixes: visibility filtering bypass in search(), unwrap panics in date parsing, DRY auth header parsing, centralized parsers module, email validation via email_address crate, value objects (Username, MimeType, RelativePath), domain events (UserCreated, UserDeleted, AlbumCreated, TagCreated, DuplicateDetected), postgres error mapping for constraint violations, OptionExt::or_not_found helper, in_memory_repo! macro, GetStackQuery moved to queries, album add_entry 200→201.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::common::errors::DomainError;
|
||||
use crate::common::value_objects::{Email, PasswordHash, SystemId};
|
||||
use crate::common::value_objects::{DateTimeStamp, Email, PasswordHash, SystemId};
|
||||
use chrono::{DateTime, Utc};
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -141,6 +141,35 @@ impl User {
|
||||
}
|
||||
}
|
||||
|
||||
// --- RefreshToken ---
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RefreshToken {
|
||||
pub token_id: SystemId,
|
||||
pub user_id: SystemId,
|
||||
pub token_hash: String,
|
||||
pub expires_at: DateTimeStamp,
|
||||
pub revoked: bool,
|
||||
pub created_at: DateTimeStamp,
|
||||
}
|
||||
|
||||
impl RefreshToken {
|
||||
pub fn new(user_id: SystemId, token_hash: String, expires_at: DateTimeStamp) -> Self {
|
||||
Self {
|
||||
token_id: SystemId::new(),
|
||||
user_id,
|
||||
token_hash,
|
||||
expires_at,
|
||||
revoked: false,
|
||||
created_at: DateTimeStamp::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_valid(&self) -> bool {
|
||||
!self.revoked && *self.expires_at.as_datetime() > Utc::now()
|
||||
}
|
||||
}
|
||||
|
||||
// --- Group ---
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
|
||||
Reference in New Issue
Block a user