feat: frontend MVP — auth, timeline, upload, albums, admin, image viewer
Backend: - user roles (DB + JWT + first-user-is-admin) - volume-aware file resolver (multi-volume asset serving) - directory scanner uses volume URI directly - date-summary endpoint (capture date from EXIF) - timeline ordered by capture date - list endpoints: volumes, plugins, pipelines, library paths - delete endpoints: volumes, library paths - configurable upload body limit (MAX_UPLOAD_BYTES) Frontend: - auth: login/register, token refresh, role-based admin gate - timeline: date-grouped grid, infinite scroll, date scrubber - image viewer: fullscreen zoom/pan/pinch, metadata sidebar - upload: drag-drop, sequential upload, progress tracking - albums: create, add/remove photos, asset picker dialog - admin: storage (import library), jobs (pagination, error details), plugins (list + toggle), pipelines, sidecars, duplicates - multi-select mode with add-to-album action - TanStack Query for all data fetching
This commit is contained in:
@@ -126,6 +126,7 @@ pub struct User {
|
||||
pub username: String,
|
||||
pub email: Email,
|
||||
pub password_hash: PasswordHash,
|
||||
pub role: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
@@ -136,9 +137,14 @@ impl User {
|
||||
username: username.into(),
|
||||
email,
|
||||
password_hash,
|
||||
role: "user".to_string(),
|
||||
created_at: Utc::now(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_admin(&self) -> bool {
|
||||
self.role == "admin"
|
||||
}
|
||||
}
|
||||
|
||||
// --- RefreshToken ---
|
||||
|
||||
@@ -12,6 +12,7 @@ pub trait UserRepository: Send + Sync {
|
||||
async fn find_by_username(&self, username: &str) -> Result<Option<User>, DomainError>;
|
||||
async fn save(&self, user: &User) -> Result<(), DomainError>;
|
||||
async fn delete(&self, id: &SystemId) -> Result<(), DomainError>;
|
||||
async fn count(&self) -> Result<u64, DomainError>;
|
||||
}
|
||||
|
||||
// --- RoleRepository ---
|
||||
|
||||
Reference in New Issue
Block a user