init
This commit is contained in:
64
libertas_api/src/handlers/album_handlers.rs
Normal file
64
libertas_api/src/handlers/album_handlers.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use axum::{
|
||||
Json, Router,
|
||||
extract::{Path, State},
|
||||
http::StatusCode,
|
||||
};
|
||||
use libertas_core::schema::{AddMediaToAlbumData, CreateAlbumData};
|
||||
use serde::Deserialize;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{error::ApiError, middleware::auth::UserId, state::AppState};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateAlbumRequest {
|
||||
name: String,
|
||||
description: Option<String>,
|
||||
is_public: Option<bool>,
|
||||
}
|
||||
|
||||
async fn create_album(
|
||||
State(state): State<AppState>,
|
||||
UserId(user_id): UserId,
|
||||
Json(payload): Json<CreateAlbumRequest>,
|
||||
) -> Result<StatusCode, ApiError> {
|
||||
let album_data = CreateAlbumData {
|
||||
owner_id: user_id,
|
||||
name: &payload.name,
|
||||
description: payload.description.as_deref(),
|
||||
is_public: payload.is_public.unwrap_or(false),
|
||||
};
|
||||
|
||||
state.album_service.create_album(album_data).await?;
|
||||
|
||||
Ok(StatusCode::CREATED)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct AddMediaToAlbumRequest {
|
||||
media_ids: Vec<Uuid>,
|
||||
}
|
||||
|
||||
async fn add_media_to_album(
|
||||
State(state): State<AppState>,
|
||||
UserId(user_id): UserId,
|
||||
Path(album_id): Path<Uuid>,
|
||||
Json(payload): Json<AddMediaToAlbumRequest>,
|
||||
) -> Result<StatusCode, ApiError> {
|
||||
let data = AddMediaToAlbumData {
|
||||
album_id,
|
||||
media_ids: payload.media_ids,
|
||||
};
|
||||
|
||||
state
|
||||
.album_service
|
||||
.add_media_to_album(data, user_id)
|
||||
.await?;
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
pub fn album_routes() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", axum::routing::post(create_album))
|
||||
.route("/{album_id}/media", axum::routing::post(add_media_to_album))
|
||||
}
|
||||
79
libertas_api/src/handlers/auth_handlers.rs
Normal file
79
libertas_api/src/handlers/auth_handlers.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use axum::{Json, extract::State, http::StatusCode};
|
||||
use libertas_core::schema::{CreateUserData, LoginUserData};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{error::ApiError, middleware::auth::UserId, state::AppState};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct RegisterRequest {
|
||||
pub username: String,
|
||||
pub email: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct UserResponse {
|
||||
id: Uuid,
|
||||
username: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
pub async fn register(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<RegisterRequest>,
|
||||
) -> Result<(StatusCode, Json<UserResponse>), ApiError> {
|
||||
let user_data = CreateUserData {
|
||||
username: &payload.username,
|
||||
email: &payload.email,
|
||||
password: &payload.password,
|
||||
};
|
||||
|
||||
let user = state.user_service.register(user_data).await?;
|
||||
|
||||
let response = UserResponse {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
};
|
||||
|
||||
Ok((StatusCode::CREATED, Json(response)))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LoginRequest {
|
||||
pub username_or_email: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LoginResponse {
|
||||
token: String,
|
||||
}
|
||||
|
||||
pub async fn login(
|
||||
State(state): State<AppState>,
|
||||
Json(payload): Json<LoginRequest>,
|
||||
) -> Result<Json<LoginResponse>, ApiError> {
|
||||
let login_data = LoginUserData {
|
||||
username_or_email: &payload.username_or_email,
|
||||
password: &payload.password,
|
||||
};
|
||||
|
||||
let token = state.user_service.login(login_data).await?;
|
||||
Ok(Json(LoginResponse { token }))
|
||||
}
|
||||
|
||||
pub async fn get_me(
|
||||
State(state): State<AppState>,
|
||||
UserId(user_id): UserId,
|
||||
) -> Result<Json<UserResponse>, ApiError> {
|
||||
let user = state.user_service.get_user_details(user_id).await?;
|
||||
|
||||
let response = UserResponse {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
};
|
||||
Ok(Json(response))
|
||||
}
|
||||
77
libertas_api/src/handlers/media_handlers.rs
Normal file
77
libertas_api/src/handlers/media_handlers.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use axum::{
|
||||
Router,
|
||||
extract::{DefaultBodyLimit, Multipart, State},
|
||||
http::StatusCode,
|
||||
response::Json,
|
||||
routing::post,
|
||||
};
|
||||
use futures::TryStreamExt;
|
||||
use libertas_core::{error::CoreError, models::Media, schema::UploadMediaData};
|
||||
use serde::Serialize;
|
||||
use std::io;
|
||||
|
||||
use crate::{error::ApiError, middleware::auth::UserId, state::AppState};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct MediaResponse {
|
||||
id: uuid::Uuid,
|
||||
storage_path: String,
|
||||
original_filename: String,
|
||||
mime_type: String,
|
||||
hash: String,
|
||||
}
|
||||
|
||||
impl From<Media> for MediaResponse {
|
||||
fn from(media: Media) -> Self {
|
||||
Self {
|
||||
id: media.id,
|
||||
storage_path: media.storage_path,
|
||||
original_filename: media.original_filename,
|
||||
mime_type: media.mime_type,
|
||||
hash: media.hash,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn media_routes() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/", post(upload_media))
|
||||
.layer(DefaultBodyLimit::max(250 * 1024 * 1024))
|
||||
}
|
||||
|
||||
async fn upload_media(
|
||||
State(state): State<AppState>,
|
||||
UserId(user_id): UserId,
|
||||
mut multipart: Multipart,
|
||||
) -> Result<(StatusCode, Json<MediaResponse>), ApiError> {
|
||||
let field = multipart
|
||||
.next_field()
|
||||
.await
|
||||
.map_err(|e| CoreError::Validation(format!("Multipart error: {}", e)))?
|
||||
.ok_or(ApiError::from(CoreError::Validation(
|
||||
"No file provided in 'file' field".to_string(),
|
||||
)))?;
|
||||
|
||||
let filename = field.file_name().unwrap_or("unknown_file").to_string();
|
||||
let mime_type = field
|
||||
.content_type()
|
||||
.unwrap_or("application/octet-stream")
|
||||
.to_string();
|
||||
|
||||
let stream = field.map_err(|e| io::Error::new(io::ErrorKind::Other, e));
|
||||
|
||||
let boxed_stream: Box<
|
||||
dyn futures::Stream<Item = Result<bytes::Bytes, std::io::Error>> + Send + Unpin,
|
||||
> = Box::new(stream);
|
||||
|
||||
let upload_data = UploadMediaData {
|
||||
owner_id: user_id,
|
||||
filename,
|
||||
mime_type,
|
||||
stream: boxed_stream,
|
||||
};
|
||||
|
||||
let media = state.media_service.upload_media(upload_data).await?;
|
||||
|
||||
Ok((StatusCode::CREATED, Json(media.into())))
|
||||
}
|
||||
3
libertas_api/src/handlers/mod.rs
Normal file
3
libertas_api/src/handlers/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub mod album_handlers;
|
||||
pub mod auth_handlers;
|
||||
pub mod media_handlers;
|
||||
Reference in New Issue
Block a user