From 5df718af71cc861f7b7ced5635a38ed9e76cb0f1 Mon Sep 17 00:00:00 2001 From: Tolmachev Igor Date: Thu, 25 Sep 2025 15:51:38 +0300 Subject: Separate queue module --- src/routers/queue/manage.rs | 233 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 src/routers/queue/manage.rs (limited to 'src/routers/queue/manage.rs') diff --git a/src/routers/queue/manage.rs b/src/routers/queue/manage.rs new file mode 100644 index 0000000..f174bd5 --- /dev/null +++ b/src/routers/queue/manage.rs @@ -0,0 +1,233 @@ +use axum::extract::State; +use entity::{queues, users}; +use sea_orm::{ + ActiveModelTrait, ActiveValue::Set, ColumnTrait, DatabaseConnection, EntityTrait, + IntoActiveModel, ModelTrait, QueryFilter, +}; +use serde::Deserialize; +use utoipa::ToSchema; +use utoipa_axum::{router::OpenApiRouter, routes}; + +use crate::{ + ApiError, ApiResult, AppState, ClientError, GlobalResponses, SuccessResponse, + extract::{ApiJson, Auth}, + models::Queue, + tags::QUEUE, +}; + +async fn user_exists(id: i64, db: &DatabaseConnection) -> Result { + Ok(users::Entity::find_by_id(id).one(db).await?.is_some()) +} + +async fn get_owned_queue( + id: i64, + owner_id: i64, + db: &DatabaseConnection, +) -> Result { + let queue = queues::Entity::find_by_id(id) + .one(db) + .await? + .ok_or(ClientError::QueueNotFound { id })?; + + if queue.owner_id != owner_id { + return Err(ClientError::NotQueueOwner { id: queue.id }.into()); + } + + Ok(queue) +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the create queue request")] +struct CreateQueueRequest { + #[schema(examples("John's queue", "Очередь Ивана"))] + name: String, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the change queue name request")] +struct ChangeQueueNameRequest { + #[schema(examples(1))] + id: i64, + #[schema(examples("John's queue", "Очередь Ивана"))] + new_name: String, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the change queue ownership request")] +struct ChangeQueueOwnershipRequest { + #[schema(examples(1))] + id: i64, + #[schema(examples(1))] + new_owner_id: i64, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the delete queue request")] +struct DeleteQueueRequest { + #[schema(examples(1))] + id: i64, +} + +#[utoipa::path( + get, + path = "/owned", + tag = QUEUE, + summary = "Get owned", + description = "Get your queues", + responses( + ( + status = 200, body = SuccessResponse>, + description = "Success response with your queues" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn owned(State(state): State, Auth(user): Auth) -> ApiResult> { + return Ok(SuccessResponse::ok( + queues::Entity::find() + .filter(queues::Column::OwnerId.eq(user.id)) + .all(&state.db) + .await? + .into_iter() + .map(Into::into) + .collect(), + )); +} + +#[utoipa::path( + post, + path = "/create", + tag = QUEUE, + summary = "Create", + description = "Create a new queue", + request_body = CreateQueueRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the created queue" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn create( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + Ok(SuccessResponse::ok( + queues::ActiveModel { + owner_id: Set(user.id), + name: Set(req.name), + ..Default::default() + } + .insert(&state.db) + .await? + .into(), + )) +} + +#[utoipa::path( + put, + path = "/change/name", + tag = QUEUE, + summary = "Change name", + description = "Change queue name", + request_body = ChangeQueueNameRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the changed queue data" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn change_name( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + let mut active_queue = get_owned_queue(req.id, user.id, &state.db) + .await? + .into_active_model(); + + active_queue.name = Set(req.new_name); + + let queue = active_queue.update(&state.db).await?; + Ok(SuccessResponse::ok(queue.into())) +} + +#[utoipa::path( + put, + path = "/change/owner", + tag = QUEUE, + summary = "Change owner", + description = "Reassign queue ownership", + request_body = ChangeQueueOwnershipRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the changed queue data" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn change_owner( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + if !user_exists(req.new_owner_id, &state.db).await? { + return Err(ClientError::UserNotFound { + id: req.new_owner_id, + } + .into()); + } + + let mut active_queue = get_owned_queue(req.id, user.id, &state.db) + .await? + .into_active_model(); + + active_queue.owner_id = Set(req.new_owner_id); + + let queue = active_queue.update(&state.db).await?; + Ok(SuccessResponse::ok(queue.into())) +} + +#[utoipa::path( + delete, + path = "/delete", + tag = QUEUE, + summary = "Delete", + description = "Delete the queue", + request_body = DeleteQueueRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the deleted queue data" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn delete( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + let queue = get_owned_queue(req.id, user.id, &state.db).await?; + queue.clone().delete(&state.db).await?; + Ok(SuccessResponse::ok(queue.into())) +} + +pub fn router() -> OpenApiRouter { + OpenApiRouter::new() + .routes(routes!(owned)) + .routes(routes!(create)) + .routes(routes!(change_name)) + .routes(routes!(change_owner)) + .routes(routes!(delete)) +} -- cgit v1.2.3