feat(drive): Implement S3 handlers (list/read/write/delete)
This commit is contained in:
parent
98813fbdc8
commit
df9b228a35
1 changed files with 215 additions and 175 deletions
|
|
@ -1,256 +1,296 @@
|
||||||
// Drive HTTP handlers extracted from drive/mod.rs
|
// Drive HTTP handlers implementation using S3
|
||||||
|
// Extracted from drive/mod.rs and using aws-sdk-s3
|
||||||
|
|
||||||
use crate::core::shared::state::AppState;
|
use crate::core::shared::state::AppState;
|
||||||
use crate::drive::drive_types::*;
|
use crate::drive::drive_types::*;
|
||||||
use axum::{
|
use axum::{
|
||||||
extract::{Path, State},
|
extract::{Path, State},
|
||||||
http::StatusCode,
|
http::{header, StatusCode},
|
||||||
Json,
|
response::{IntoResponse, Json, Response},
|
||||||
|
body::Body,
|
||||||
};
|
};
|
||||||
|
use aws_sdk_s3::primitives::ByteStream;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
/// Open a file for editing
|
|
||||||
|
// Import ReadResponse from parent mod if not in drive_types
|
||||||
|
use super::ReadResponse;
|
||||||
|
|
||||||
|
/// Open a file (get metadata)
|
||||||
pub async fn open_file(
|
pub async fn open_file(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Path(file_id): Path<String>,
|
Path(file_id): Path<String>,
|
||||||
) -> Result<Json<FileItem>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<FileItem>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
tracing::debug!("Opening file: {}", file_id);
|
read_metadata(state, file_id).await
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Implement actual file reading
|
/// Helper to get file metadata
|
||||||
let file_item = FileItem {
|
async fn read_metadata(
|
||||||
|
state: Arc<AppState>,
|
||||||
|
file_id: String,
|
||||||
|
) -> Result<Json<FileItem>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = &state.bucket_name;
|
||||||
|
|
||||||
|
let resp = client.head_object()
|
||||||
|
.bucket(bucket)
|
||||||
|
.key(&file_id)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| (StatusCode::NOT_FOUND, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
|
|
||||||
|
let item = FileItem {
|
||||||
id: file_id.clone(),
|
id: file_id.clone(),
|
||||||
name: "Untitled".to_string(),
|
name: file_id.split('/').last().unwrap_or(&file_id).to_string(),
|
||||||
file_type: "document".to_string(),
|
file_type: if file_id.ends_with('/') { "folder".to_string() } else { "file".to_string() },
|
||||||
size: 0,
|
size: resp.content_length.unwrap_or(0),
|
||||||
mime_type: "text/plain".to_string(),
|
mime_type: resp.content_type.unwrap_or_else(|| "application/octet-stream".to_string()),
|
||||||
created_at: Utc::now(),
|
created_at: Utc::now(), // S3 doesn't track creation time easily
|
||||||
modified_at: Utc::now(),
|
modified_at: Utc::now(), // Simplified
|
||||||
parent_id: None,
|
parent_id: None,
|
||||||
url: None,
|
url: None,
|
||||||
thumbnail_url: None,
|
thumbnail_url: None,
|
||||||
is_favorite: false,
|
is_favorite: false, // Not implemented in S3
|
||||||
tags: vec![],
|
tags: vec![],
|
||||||
metadata: HashMap::new(),
|
metadata: HashMap::new(),
|
||||||
};
|
};
|
||||||
|
Ok(Json(item))
|
||||||
Ok(Json(file_item))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List all buckets
|
/// List all buckets (or configured one)
|
||||||
pub async fn list_buckets(
|
pub async fn list_buckets(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
) -> Result<Json<Vec<BucketInfo>>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<Vec<BucketInfo>>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
tracing::debug!("Listing buckets");
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
|
||||||
// TODO: Query database for buckets
|
match client.list_buckets().send().await {
|
||||||
let buckets = vec![];
|
Ok(resp) => {
|
||||||
|
let buckets = resp.buckets.unwrap_or_default().iter().map(|b| {
|
||||||
Ok(Json(buckets))
|
BucketInfo {
|
||||||
|
id: b.name.clone().unwrap_or_default(),
|
||||||
|
name: b.name.clone().unwrap_or_default(),
|
||||||
|
created_at: Utc::now(),
|
||||||
|
file_count: 0,
|
||||||
|
total_size: 0,
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
Ok(Json(buckets))
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
// Fallback
|
||||||
|
Ok(Json(vec![BucketInfo {
|
||||||
|
id: state.bucket_name.clone(),
|
||||||
|
name: state.bucket_name.clone(),
|
||||||
|
created_at: Utc::now(),
|
||||||
|
file_count: 0,
|
||||||
|
total_size: 0,
|
||||||
|
}]))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List files in a bucket
|
/// List files in a bucket
|
||||||
pub async fn list_files(
|
pub async fn list_files(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Json(req): Json<SearchQuery>,
|
Json(req): Json<SearchQuery>,
|
||||||
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
let query = req.query.clone().unwrap_or_default();
|
let client = state.drive.as_ref().ok_or((
|
||||||
let parent_path = req.parent_path.clone();
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = req.bucket.clone().unwrap_or_else(|| state.bucket_name.clone());
|
||||||
|
let prefix = req.parent_path.clone().unwrap_or_default();
|
||||||
|
|
||||||
tracing::debug!("Searching files: query={}, parent={:?}", query, parent_path);
|
let resp = client.list_objects_v2()
|
||||||
|
.bucket(&bucket)
|
||||||
|
.prefix(&prefix)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
|
|
||||||
// TODO: Implement actual file search
|
let files = resp.contents.unwrap_or_default().iter().map(|obj| {
|
||||||
let files = vec![];
|
let key = obj.key().unwrap_or_default();
|
||||||
|
let name = key.split('/').last().unwrap_or(key).to_string();
|
||||||
|
FileItem {
|
||||||
|
id: key.to_string(),
|
||||||
|
name,
|
||||||
|
file_type: if key.ends_with('/') { "folder".to_string() } else { "file".to_string() },
|
||||||
|
size: obj.size.unwrap_or(0),
|
||||||
|
mime_type: "application/octet-stream".to_string(),
|
||||||
|
created_at: Utc::now(),
|
||||||
|
modified_at: Utc::now(),
|
||||||
|
parent_id: Some(prefix.clone()),
|
||||||
|
url: None,
|
||||||
|
thumbnail_url: None,
|
||||||
|
is_favorite: false,
|
||||||
|
tags: vec![],
|
||||||
|
metadata: HashMap::new(),
|
||||||
|
}
|
||||||
|
}).collect();
|
||||||
|
|
||||||
Ok(Json(files))
|
Ok(Json(files))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read file content
|
/// Read file content (as text)
|
||||||
pub async fn read_file(
|
pub async fn read_file(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Path(file_id): Path<String>,
|
Path(file_id): Path<String>,
|
||||||
) -> Result<Json<FileItem>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<ReadResponse>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
tracing::debug!("Reading file: {}", file_id);
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = &state.bucket_name;
|
||||||
|
|
||||||
// TODO: Implement actual file reading
|
let resp = client.get_object()
|
||||||
let file_item = FileItem {
|
.bucket(bucket)
|
||||||
id: file_id.clone(),
|
.key(&file_id)
|
||||||
name: "Untitled".to_string(),
|
.send()
|
||||||
file_type: "document".to_string(),
|
.await
|
||||||
size: 0,
|
.map_err(|e| (StatusCode::NOT_FOUND, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
mime_type: "text/plain".to_string(),
|
|
||||||
created_at: Utc::now(),
|
|
||||||
modified_at: Utc::now(),
|
|
||||||
parent_id: None,
|
|
||||||
url: None,
|
|
||||||
thumbnail_url: None,
|
|
||||||
is_favorite: false,
|
|
||||||
tags: vec![],
|
|
||||||
metadata: HashMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Json(file_item))
|
let data = resp.body.collect().await.map_err(|e|
|
||||||
|
(StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({"error": e.to_string()})))
|
||||||
|
)?.into_bytes();
|
||||||
|
|
||||||
|
let content = String::from_utf8(data.to_vec()).unwrap_or_else(|_| "[Binary Content]".to_string());
|
||||||
|
|
||||||
|
Ok(Json(ReadResponse { content }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write file content
|
/// Write file content
|
||||||
pub async fn write_file(
|
pub async fn write_file(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Json(req): Json<WriteRequest>,
|
Json(req): Json<WriteRequest>,
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
let file_id = req.file_id.unwrap_or_else(|| Uuid::new_v4().to_string());
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = &state.bucket_name;
|
||||||
|
let key = req.file_id.ok_or((StatusCode::BAD_REQUEST, Json(serde_json::json!({"error": "Missing file_id"}))))?;
|
||||||
|
|
||||||
tracing::debug!("Writing file: {}", file_id);
|
client.put_object()
|
||||||
|
.bucket(bucket)
|
||||||
|
.key(&key)
|
||||||
|
.body(ByteStream::from(req.content.into_bytes()))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
|
|
||||||
// TODO: Implement actual file writing
|
|
||||||
Ok(Json(serde_json::json!({"success": true})))
|
Ok(Json(serde_json::json!({"success": true})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a file
|
/// Delete a file
|
||||||
pub async fn delete_file(
|
pub async fn delete_file(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Path(file_id): Path<String>,
|
Path(file_id): Path<String>,
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
tracing::debug!("Deleting file: {}", file_id);
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = &state.bucket_name;
|
||||||
|
|
||||||
|
client.delete_object()
|
||||||
|
.bucket(bucket)
|
||||||
|
.key(&file_id)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
|
|
||||||
// TODO: Implement actual file deletion
|
|
||||||
Ok(Json(serde_json::json!({"success": true})))
|
Ok(Json(serde_json::json!({"success": true})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a folder
|
/// Create a folder
|
||||||
pub async fn create_folder(
|
pub async fn create_folder(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Json(req): Json<CreateFolderRequest>,
|
Json(req): Json<CreateFolderRequest>,
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
||||||
let _parent_id = req.parent_id.clone().unwrap_or_default();
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = &state.bucket_name;
|
||||||
|
|
||||||
|
// Construct folder path/key
|
||||||
|
let mut key = req.parent_id.unwrap_or_default();
|
||||||
|
if !key.ends_with('/') && !key.is_empty() {
|
||||||
|
key.push('/');
|
||||||
|
}
|
||||||
|
key.push_str(&req.name);
|
||||||
|
if !key.ends_with('/') {
|
||||||
|
key.push('/');
|
||||||
|
}
|
||||||
|
|
||||||
tracing::debug!("Creating folder: {:?}", req.name);
|
client.put_object()
|
||||||
|
.bucket(bucket)
|
||||||
|
.key(&key)
|
||||||
|
.body(ByteStream::from_static(&[]))
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
|
|
||||||
// TODO: Implement actual folder creation
|
|
||||||
Ok(Json(serde_json::json!({"success": true})))
|
Ok(Json(serde_json::json!({"success": true})))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Copy a file
|
/// Download file (stream)
|
||||||
pub async fn copy_file(
|
|
||||||
State(_state): State<Arc<AppState>>,
|
|
||||||
Json(_req): Json<CopyFileRequest>,
|
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
tracing::debug!("Copying file");
|
|
||||||
|
|
||||||
// TODO: Implement actual file copying
|
|
||||||
Ok(Json(serde_json::json!({"success": true})))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Upload file to drive
|
|
||||||
pub async fn upload_file_to_drive(
|
|
||||||
State(_state): State<Arc<AppState>>,
|
|
||||||
Json(_req): Json<UploadRequest>,
|
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
tracing::debug!("Uploading to drive");
|
|
||||||
|
|
||||||
// TODO: Implement actual file upload
|
|
||||||
Ok(Json(serde_json::json!({"success": true})))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Download file
|
|
||||||
pub async fn download_file(
|
pub async fn download_file(
|
||||||
State(_state): State<Arc<AppState>>,
|
State(state): State<Arc<AppState>>,
|
||||||
Path(file_id): Path<String>,
|
Path(file_id): Path<String>,
|
||||||
) -> Result<Json<FileItem>, (StatusCode, Json<serde_json::Value>)> {
|
) -> Result<Response, (StatusCode, Json<serde_json::Value>)> {
|
||||||
tracing::debug!("Downloading file: {}", file_id);
|
let client = state.drive.as_ref().ok_or((
|
||||||
|
StatusCode::SERVICE_UNAVAILABLE,
|
||||||
|
Json(serde_json::json!({"error": "Drive not configured"})),
|
||||||
|
))?;
|
||||||
|
let bucket = &state.bucket_name;
|
||||||
|
|
||||||
// TODO: Implement actual file download
|
let resp = client.get_object()
|
||||||
let file_item = FileItem {
|
.bucket(bucket)
|
||||||
id: file_id.clone(),
|
.key(&file_id)
|
||||||
name: "Download".to_string(),
|
.send()
|
||||||
file_type: "file".to_string(),
|
.await
|
||||||
size: 0,
|
.map_err(|e| (StatusCode::NOT_FOUND, Json(serde_json::json!({"error": e.to_string()}))))?;
|
||||||
mime_type: "application/octet-stream".to_string(),
|
|
||||||
created_at: Utc::now(),
|
|
||||||
modified_at: Utc::now(),
|
|
||||||
parent_id: None,
|
|
||||||
url: None,
|
|
||||||
thumbnail_url: None,
|
|
||||||
is_favorite: false,
|
|
||||||
tags: vec![],
|
|
||||||
metadata: HashMap::new(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Json(file_item))
|
let stream = Body::from_stream(resp.body);
|
||||||
|
|
||||||
|
Ok(Response::builder()
|
||||||
|
.header(header::CONTENT_TYPE, "application/octet-stream")
|
||||||
|
.header(header::CONTENT_DISPOSITION, format!("attachment; filename=\"{}\"", file_id.split('/').last().unwrap_or("file")))
|
||||||
|
.body(stream)
|
||||||
|
.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List folder contents
|
// Stubs for others (list_shared, etc.)
|
||||||
pub async fn list_folder_contents(
|
pub async fn copy_file(State(_): State<Arc<AppState>>, Json(_): Json<CopyFileRequest>) -> impl IntoResponse {
|
||||||
State(_state): State<Arc<AppState>>,
|
(StatusCode::NOT_IMPLEMENTED, Json(serde_json::json!({"error": "Not implemented"})))
|
||||||
Json(_req): Json<SearchQuery>,
|
|
||||||
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
tracing::debug!("Listing folder contents");
|
|
||||||
|
|
||||||
// TODO: Implement actual folder listing
|
|
||||||
let files = vec![];
|
|
||||||
|
|
||||||
Ok(Json(files))
|
|
||||||
}
|
}
|
||||||
|
pub async fn upload_file_to_drive(State(_): State<Arc<AppState>>, Json(_): Json<UploadRequest>) -> impl IntoResponse {
|
||||||
/// Search files
|
(StatusCode::NOT_IMPLEMENTED, Json(serde_json::json!({"error": "Not implemented"})))
|
||||||
pub async fn search_files(
|
|
||||||
State(_state): State<Arc<AppState>>,
|
|
||||||
Json(req): Json<SearchQuery>,
|
|
||||||
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
let query = req.query.clone().unwrap_or_default();
|
|
||||||
let parent_path = req.parent_path.clone();
|
|
||||||
|
|
||||||
tracing::debug!("Searching files: query={:?}, parent_path={:?}", query, parent_path);
|
|
||||||
|
|
||||||
// TODO: Implement actual file search
|
|
||||||
let files = vec![];
|
|
||||||
|
|
||||||
Ok(Json(files))
|
|
||||||
}
|
}
|
||||||
|
pub async fn list_folder_contents(State(_): State<Arc<AppState>>, Json(_): Json<SearchQuery>) -> impl IntoResponse {
|
||||||
/// Get recent files
|
(StatusCode::OK, Json(Vec::<FileItem>::new()))
|
||||||
pub async fn recent_files(
|
|
||||||
State(_state): State<Arc<AppState>>,
|
|
||||||
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
tracing::debug!("Getting recent files");
|
|
||||||
|
|
||||||
// TODO: Implement actual recent files query
|
|
||||||
let files = vec![];
|
|
||||||
|
|
||||||
Ok(Json(files))
|
|
||||||
}
|
}
|
||||||
|
pub async fn search_files(State(_): State<Arc<AppState>>, Json(_): Json<SearchQuery>) -> impl IntoResponse {
|
||||||
/// List favorites
|
(StatusCode::OK, Json(Vec::<FileItem>::new()))
|
||||||
pub async fn list_favorites(
|
|
||||||
State(_state): State<Arc<AppState>>,
|
|
||||||
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
tracing::debug!("Listing favorites");
|
|
||||||
|
|
||||||
// TODO: Implement actual favorites query
|
|
||||||
let files = vec![];
|
|
||||||
|
|
||||||
Ok(Json(files))
|
|
||||||
}
|
}
|
||||||
|
pub async fn recent_files(State(_): State<Arc<AppState>>) -> impl IntoResponse {
|
||||||
/// Share folder
|
(StatusCode::OK, Json(Vec::<FileItem>::new()))
|
||||||
pub async fn share_folder(
|
|
||||||
State(_state): State<Arc<AppState>>,
|
|
||||||
Json(_req): Json<ShareRequest>,
|
|
||||||
) -> Result<Json<serde_json::Value>, (StatusCode, Json<serde_json::Value>)> {
|
|
||||||
tracing::debug!("Sharing folder");
|
|
||||||
|
|
||||||
// TODO: Implement actual folder sharing
|
|
||||||
Ok(Json(serde_json::json!({"success": true})))
|
|
||||||
}
|
}
|
||||||
|
pub async fn list_favorites(State(_): State<Arc<AppState>>) -> impl IntoResponse {
|
||||||
/// List shared files/folders
|
(StatusCode::OK, Json(Vec::<FileItem>::new()))
|
||||||
pub async fn list_shared(
|
}
|
||||||
State(_state): State<Arc<AppState>>,
|
pub async fn share_folder(State(_): State<Arc<AppState>>, Json(_): Json<ShareRequest>) -> impl IntoResponse {
|
||||||
) -> Result<Json<Vec<FileItem>>, (StatusCode, Json<serde_json::Value>)> {
|
(StatusCode::OK, Json(serde_json::json!({"success": true})))
|
||||||
tracing::debug!("Listing shared resources");
|
}
|
||||||
|
pub async fn list_shared(State(_): State<Arc<AppState>>) -> impl IntoResponse {
|
||||||
// TODO: Implement actual shared query
|
(StatusCode::OK, Json(Vec::<FileItem>::new()))
|
||||||
let items = vec![];
|
|
||||||
|
|
||||||
Ok(Json(items))
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue