f2d35ca792
- JWT secret auto-generates and persists to <STORAGE_PATH>/.jwt_secret - Remove setup token: first admin setup is open until system initialized - Fix schema.sql: move CREATE EXTENSION pg_trgm/ltree to top - Update login UI and auth.js to remove setup token fields
111 lines
3.2 KiB
Rust
Executable File
111 lines
3.2 KiB
Rust
Executable File
use crate::application::dtos::recent_dto::RecentItemDto;
|
|
use crate::application::ports::recent_ports::{RecentItemsRepositoryPort, RecentItemsUseCase};
|
|
use crate::common::errors::{DomainError, ErrorKind, Result};
|
|
use crate::infrastructure::repositories::pg::RecentItemsPgRepository;
|
|
use std::sync::Arc;
|
|
use tracing::info;
|
|
|
|
/// Implementation of the use case for managing recent items.
|
|
///
|
|
/// Depends on `RecentItemsRepositoryPort` (outbound port) instead
|
|
/// of accessing `PgPool` directly, following the hexagonal architecture.
|
|
pub struct RecentService {
|
|
repo: Arc<RecentItemsPgRepository>,
|
|
max_recent_items: i32,
|
|
}
|
|
|
|
impl RecentService {
|
|
/// Create a new recent items service
|
|
pub fn new(repo: Arc<RecentItemsPgRepository>, max_recent_items: i32) -> Self {
|
|
Self {
|
|
repo,
|
|
max_recent_items: max_recent_items.clamp(1, 100),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl RecentItemsUseCase for RecentService {
|
|
/// Get recent items for a user
|
|
async fn get_recent_items(
|
|
&self,
|
|
user_id: &str,
|
|
limit: Option<i32>,
|
|
) -> Result<Vec<RecentItemDto>> {
|
|
info!("Getting recent items for user: {}", user_id);
|
|
let limit_value = limit
|
|
.unwrap_or(self.max_recent_items)
|
|
.min(self.max_recent_items);
|
|
let items = self.repo.get_recent_items(user_id, limit_value).await?;
|
|
info!(
|
|
"Retrieved {} recent items for user {}",
|
|
items.len(),
|
|
user_id
|
|
);
|
|
Ok(items)
|
|
}
|
|
|
|
/// Record access to an item
|
|
async fn record_item_access(
|
|
&self,
|
|
user_id: &str,
|
|
item_id: &str,
|
|
item_type: &str,
|
|
) -> Result<()> {
|
|
info!(
|
|
"Recording access to {} '{}' for user {}",
|
|
item_type, item_id, user_id
|
|
);
|
|
|
|
if item_type != "file" && item_type != "folder" {
|
|
return Err(DomainError::new(
|
|
ErrorKind::InvalidInput,
|
|
"RecentItems",
|
|
"Item type must be 'file' or 'folder'",
|
|
));
|
|
}
|
|
|
|
self.repo.upsert_access(user_id, item_id, item_type).await?;
|
|
self.repo.prune(user_id, self.max_recent_items).await?;
|
|
|
|
info!(
|
|
"Successfully recorded access to {} '{}' for user {}",
|
|
item_type, item_id, user_id
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
/// Remove an item from recent
|
|
async fn remove_from_recent(
|
|
&self,
|
|
user_id: &str,
|
|
item_id: &str,
|
|
item_type: &str,
|
|
) -> Result<bool> {
|
|
info!(
|
|
"Removing {} '{}' from recent for user {}",
|
|
item_type, item_id, user_id
|
|
);
|
|
let removed = self.repo.remove_item(user_id, item_id, item_type).await?;
|
|
info!(
|
|
"{} {} '{}' from recent items for user {}",
|
|
if removed {
|
|
"Successfully removed"
|
|
} else {
|
|
"Not found"
|
|
},
|
|
item_type,
|
|
item_id,
|
|
user_id
|
|
);
|
|
Ok(removed)
|
|
}
|
|
|
|
/// Clear all recent items
|
|
async fn clear_recent_items(&self, user_id: &str) -> Result<()> {
|
|
info!("Clearing all recent items for user {}", user_id);
|
|
self.repo.clear_all(user_id).await?;
|
|
info!("Cleared all recent items for user {}", user_id);
|
|
Ok(())
|
|
}
|
|
}
|