litecloud/api/src/routes/shares.rs
2025-05-28 22:40:43 +02:00

89 lines
2.8 KiB
Rust

use axum::{
extract::{Extension, Path},
http::StatusCode,
routing::{delete, get, post},
Json, Router,
};
use sqlx::PgPool;
use uuid::Uuid;
use crate::error::AppError;
use crate::models::share::{CreateShareDto, Share, ShareResponse};
use crate::services::auth::AuthUser;
pub fn routes() -> Router {
Router::new()
.route("/shares", get(list_shares))
.route("/shares", post(create_share))
.route("/shares/:id", get(get_share))
.route("/shares/:id", delete(delete_share))
.route("/shares/access/:access_key", get(access_shared_file))
}
async fn list_shares(
auth_user: AuthUser,
Extension(pool): Extension<PgPool>,
) -> Result<Json<Vec<ShareResponse>>, AppError> {
let owned_shares = Share::list_by_owner(&pool, auth_user.id).await?;
let received_shares = Share::list_by_recipient(&pool, auth_user.id).await?;
let mut share_responses = Vec::new();
for share in owned_shares {
let share_response = Share::get_full_share_details(&pool, share.id).await?;
share_responses.push(share_response);
}
for share in received_shares {
let share_response = Share::get_full_share_details(&pool, share.id).await?;
share_responses.push(share_response);
}
Ok(Json(share_responses))
}
async fn create_share(
auth_user: AuthUser,
Extension(pool): Extension<PgPool>,
Json(create_share_dto): Json<CreateShareDto>,
) -> Result<Json<Share>, AppError> {
let share = Share::create(&pool, auth_user.id, create_share_dto).await?;
Ok(Json(share))
}
async fn get_share(
auth_user: AuthUser,
Extension(pool): Extension<PgPool>,
Path(id): Path<Uuid>,
) -> Result<Json<ShareResponse>, AppError> {
let share = Share::find_by_id(&pool, id).await?;
if share.owner_id != auth_user.id && share.recipient_id != Some(auth_user.id) {
return Err(AppError::AccessDenied("You don't have access to this share".to_string()));
}
let share_response = Share::get_full_share_details(&pool, id).await?;
Ok(Json(share_response))
}
async fn delete_share(
auth_user: AuthUser,
Extension(pool): Extension<PgPool>,
Path(id): Path<Uuid>,
) -> Result<StatusCode, AppError> {
Share::delete(&pool, id, auth_user.id).await?;
Ok(StatusCode::NO_CONTENT)
}
async fn access_shared_file(
Extension(pool): Extension<PgPool>,
Path(access_key): Path<String>,
) -> Result<Json<ShareResponse>, AppError> {
let share = Share::find_by_access_key(&pool, &access_key).await?;
if let Some(expires_at) = share.expires_at {
if expires_at < time::OffsetDateTime::now_utc() {
return Err(AppError::AccessDenied("This share has expired".to_string()));
}
}
let share_response = Share::get_full_share_details(&pool, share.id).await?;
Ok(Json(share_response))
}