2025-04-02 05:08:30 +02:00
|
|
|
use axum::{
|
2026-02-14 01:29:34 +01:00
|
|
|
Json,
|
|
|
|
|
extract::{Path, Query, State},
|
2025-04-02 05:08:30 +02:00
|
|
|
http::StatusCode,
|
|
|
|
|
response::IntoResponse,
|
|
|
|
|
};
|
2025-04-04 21:31:41 +02:00
|
|
|
use serde::Deserialize;
|
2026-02-14 01:29:34 +01:00
|
|
|
use std::sync::Arc;
|
2025-04-02 05:08:30 +02:00
|
|
|
use tracing::{error, info};
|
|
|
|
|
|
|
|
|
|
use crate::application::ports::recent_ports::RecentItemsUseCase;
|
2026-03-03 15:36:42 +00:00
|
|
|
use crate::application::services::recent_service::RecentService;
|
2026-03-04 23:55:08 +01:00
|
|
|
use crate::interfaces::middleware::auth::AuthUser;
|
2025-04-02 05:08:30 +02:00
|
|
|
|
2026-02-12 09:41:25 +01:00
|
|
|
/// Query parameters for getting recent items
|
2025-04-02 05:08:30 +02:00
|
|
|
#[derive(Deserialize)]
|
|
|
|
|
pub struct GetRecentParams {
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
limit: Option<i32>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 09:41:25 +01:00
|
|
|
/// Get user's recent items
|
2025-04-02 05:08:30 +02:00
|
|
|
pub async fn get_recent_items(
|
2026-03-03 15:36:42 +00:00
|
|
|
State(recent_service): State<Arc<RecentService>>,
|
2026-02-07 04:02:38 +01:00
|
|
|
auth_user: AuthUser,
|
2025-04-02 05:08:30 +02:00
|
|
|
Query(params): Query<GetRecentParams>,
|
|
|
|
|
) -> impl IntoResponse {
|
2026-02-07 04:02:38 +01:00
|
|
|
let user_id = &auth_user.id;
|
2026-02-14 01:29:34 +01:00
|
|
|
|
2025-04-02 05:08:30 +02:00
|
|
|
match recent_service.get_recent_items(user_id, params.limit).await {
|
|
|
|
|
Ok(items) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
info!("Retrieved {} recent items for user", items.len());
|
2025-04-02 05:08:30 +02:00
|
|
|
(StatusCode::OK, Json(items)).into_response()
|
2026-02-14 01:29:34 +01:00
|
|
|
}
|
2025-04-02 05:08:30 +02:00
|
|
|
Err(err) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
error!("Error retrieving recent items: {}", err);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-03-05 13:15:34 +01:00
|
|
|
"error": "Failed to retrieve recent items"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
2025-04-02 05:08:30 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 09:41:25 +01:00
|
|
|
/// Record access to an item
|
2025-04-02 05:08:30 +02:00
|
|
|
pub async fn record_item_access(
|
2026-03-03 15:36:42 +00:00
|
|
|
State(recent_service): State<Arc<RecentService>>,
|
2026-02-07 04:02:38 +01:00
|
|
|
auth_user: AuthUser,
|
2025-04-02 05:08:30 +02:00
|
|
|
Path((item_type, item_id)): Path<(String, String)>,
|
|
|
|
|
) -> impl IntoResponse {
|
2026-02-07 04:02:38 +01:00
|
|
|
let user_id = &auth_user.id;
|
2026-02-14 01:29:34 +01:00
|
|
|
|
2026-02-12 09:41:25 +01:00
|
|
|
// Validate item type
|
2025-04-02 05:08:30 +02:00
|
|
|
if item_type != "file" && item_type != "folder" {
|
|
|
|
|
return (
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::BAD_REQUEST,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-02-12 09:41:25 +01:00
|
|
|
"error": "Item type must be 'file' or 'folder'"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response();
|
2025-04-02 05:08:30 +02:00
|
|
|
}
|
2026-02-14 01:29:34 +01:00
|
|
|
|
|
|
|
|
match recent_service
|
|
|
|
|
.record_item_access(user_id, &item_id, &item_type)
|
|
|
|
|
.await
|
|
|
|
|
{
|
2025-04-02 05:08:30 +02:00
|
|
|
Ok(_) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
info!("Recorded access to {} '{}' in recents", item_type, item_id);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::OK,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-02-12 09:41:25 +01:00
|
|
|
"message": "Access recorded successfully"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
|
|
|
|
}
|
2025-04-02 05:08:30 +02:00
|
|
|
Err(err) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
error!("Error recording access in recents: {}", err);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-03-05 13:15:34 +01:00
|
|
|
"error": "Failed to record access"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
2025-04-02 05:08:30 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 09:41:25 +01:00
|
|
|
/// Remove an item from recents
|
2025-04-02 05:08:30 +02:00
|
|
|
pub async fn remove_from_recent(
|
2026-03-03 15:36:42 +00:00
|
|
|
State(recent_service): State<Arc<RecentService>>,
|
2026-02-07 04:02:38 +01:00
|
|
|
auth_user: AuthUser,
|
2025-04-02 05:08:30 +02:00
|
|
|
Path((item_type, item_id)): Path<(String, String)>,
|
|
|
|
|
) -> impl IntoResponse {
|
2026-02-07 04:02:38 +01:00
|
|
|
let user_id = &auth_user.id;
|
2026-02-14 01:29:34 +01:00
|
|
|
|
|
|
|
|
match recent_service
|
|
|
|
|
.remove_from_recent(user_id, &item_id, &item_type)
|
|
|
|
|
.await
|
|
|
|
|
{
|
2025-04-02 05:08:30 +02:00
|
|
|
Ok(removed) => {
|
|
|
|
|
if removed {
|
2026-02-12 09:41:25 +01:00
|
|
|
info!("Removed {} '{}' from recents", item_type, item_id);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::OK,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-02-12 09:41:25 +01:00
|
|
|
"message": "Item removed from recents"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
2025-04-02 05:08:30 +02:00
|
|
|
} else {
|
2026-02-12 09:41:25 +01:00
|
|
|
info!("Item {} '{}' was not in recents", item_type, item_id);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::NOT_FOUND,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-02-12 09:41:25 +01:00
|
|
|
"message": "Item was not in recents"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
2025-04-02 05:08:30 +02:00
|
|
|
}
|
2026-02-14 01:29:34 +01:00
|
|
|
}
|
2025-04-02 05:08:30 +02:00
|
|
|
Err(err) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
error!("Error removing from recents: {}", err);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-03-05 13:15:34 +01:00
|
|
|
"error": "Failed to remove from recents"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
2025-04-02 05:08:30 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 09:41:25 +01:00
|
|
|
/// Clear all recent items
|
2025-04-02 05:08:30 +02:00
|
|
|
pub async fn clear_recent_items(
|
2026-03-03 15:36:42 +00:00
|
|
|
State(recent_service): State<Arc<RecentService>>,
|
2026-02-07 04:02:38 +01:00
|
|
|
auth_user: AuthUser,
|
2025-04-02 05:08:30 +02:00
|
|
|
) -> impl IntoResponse {
|
2026-02-07 04:02:38 +01:00
|
|
|
let user_id = &auth_user.id;
|
2026-02-14 01:29:34 +01:00
|
|
|
|
2025-04-02 05:08:30 +02:00
|
|
|
match recent_service.clear_recent_items(user_id).await {
|
|
|
|
|
Ok(_) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
info!("Cleared all recent items for user");
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::OK,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-02-12 09:41:25 +01:00
|
|
|
"message": "Recent items cleared successfully"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
|
|
|
|
}
|
2025-04-02 05:08:30 +02:00
|
|
|
Err(err) => {
|
2026-02-12 09:41:25 +01:00
|
|
|
error!("Error clearing recent items: {}", err);
|
2025-04-02 05:08:30 +02:00
|
|
|
(
|
2026-02-14 01:29:34 +01:00
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
2025-04-02 05:08:30 +02:00
|
|
|
Json(serde_json::json!({
|
2026-03-05 13:15:34 +01:00
|
|
|
"error": "Failed to clear recent items"
|
2026-02-14 01:29:34 +01:00
|
|
|
})),
|
|
|
|
|
)
|
|
|
|
|
.into_response()
|
2025-04-02 05:08:30 +02:00
|
|
|
}
|
|
|
|
|
}
|
2026-02-14 01:29:34 +01:00
|
|
|
}
|