89 lines
2.8 KiB
Rust
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))
|
|
} |