From e864d2653d50ba1c920776aaa14a1625c9fc9da4 Mon Sep 17 00:00:00 2001 From: Tolmachev Igor Date: Wed, 22 Oct 2025 17:00:28 +0300 Subject: Add invite tokens --- src/routers/queue/access.rs | 257 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 255 insertions(+), 2 deletions(-) (limited to 'src/routers/queue/access.rs') diff --git a/src/routers/queue/access.rs b/src/routers/queue/access.rs index 1cba0b1..1aee8da 100644 --- a/src/routers/queue/access.rs +++ b/src/routers/queue/access.rs @@ -1,7 +1,260 @@ -use utoipa_axum::router::OpenApiRouter; +use axum::extract::State; +use chrono::{DateTime, Utc}; +use entity::invite_tokens; +use sea_orm::{ActiveModelTrait, ActiveValue::Set, IntoActiveModel, ModelTrait}; +use serde::Deserialize; +use utoipa::{IntoParams, ToSchema}; +use utoipa_axum::{router::OpenApiRouter, routes}; -use crate::AppState; +use crate::{ + ApiResult, AppState, GlobalResponses, SuccessResponse, + extract::{ApiJson, ApiQuery, Auth}, + models::InviteToken, + tags::INVITE_TOKEN, + util::{get_owned_invite_token, get_owned_queue}, +}; + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Query)] +struct GetInviteTokenByIdQuery { + #[param(example = 1)] + id: i64, +} + +#[derive(Deserialize, IntoParams)] +#[into_params(parameter_in = Query)] +struct GetInviteTokenByQueueIdQuery { + #[param(example = 1)] + queue_id: i64, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the create invite token request")] +struct CreateInviteTokenRequest { + #[schema(examples(1))] + queue_id: i64, + #[schema(examples("For classmates", "Для однокурсников"))] + name: String, + expiration_date: Option>, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the expire invite token request")] +struct ExpireInviteTokenRequest { + #[schema(examples(1))] + id: i64, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the change invite token expiration date request")] +struct ChangeInviteTokenExpirationDateRequest { + #[schema(examples(1))] + id: i64, + #[schema(examples("2000-01-01 00:00:00Z", "2000-01-01 03:00:00+03:00", json!(null)))] + expiration_date: Option>, +} + +#[derive(Deserialize, ToSchema)] +#[schema(description = "Body of the delete invite token request")] +struct DeleteInviteTokenRequest { + #[schema(examples(1))] + id: i64, +} + +#[utoipa::path( + get, + path = "/get/by_id", + tag = INVITE_TOKEN, + summary = "Get by id", + description = "Get the invite token by id", + params(GetInviteTokenByIdQuery), + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the requested invite token" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn get_by_id( + State(state): State, + Auth(user): Auth, + ApiQuery(req): ApiQuery, +) -> ApiResult { + Ok(SuccessResponse::ok( + get_owned_invite_token(req.id, user.id, &state.db) + .await? + .into(), + )) +} + +#[utoipa::path( + get, + path = "/get/by_queue_id", + tag = INVITE_TOKEN, + summary = "Get by queue id", + description = "Get the invite token by the queue id", + params(GetInviteTokenByQueueIdQuery), + responses( + ( + status = 200, body = SuccessResponse>, + description = "Success response with the requested invite tokens" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn get_by_queue_id( + State(state): State, + Auth(user): Auth, + ApiQuery(req): ApiQuery, +) -> ApiResult> { + let queue = get_owned_queue(req.queue_id, user.id, &state.db).await?; + + Ok(SuccessResponse::ok( + queue + .find_related(invite_tokens::Entity) + .all(&state.db) + .await? + .into_iter() + .map(Into::into) + .collect(), + )) +} + +#[utoipa::path( + post, + path = "/create", + tag = INVITE_TOKEN, + summary = "Create", + description = "Create a new invite token", + request_body = CreateInviteTokenRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the created invite token" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn create( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + let queue = get_owned_queue(req.queue_id, user.id, &state.db).await?; + + Ok(SuccessResponse::ok( + invite_tokens::ActiveModel { + token: Set(uuid::Uuid::new_v4()), + queue_id: Set(queue.id), + name: Set(req.name), + expiration_date: Set(req.expiration_date.as_ref().map(DateTime::naive_utc)), + ..Default::default() + } + .insert(&state.db) + .await? + .into(), + )) +} + +#[utoipa::path( + patch, + path = "/expire", + tag = INVITE_TOKEN, + summary = "Expire", + description = "Expire the invite token", + request_body = ExpireInviteTokenRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the changed invite token data" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn expire( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + let mut active_invite_token = get_owned_invite_token(req.id, user.id, &state.db) + .await? + .into_active_model(); + + active_invite_token.expiration_date = Set(Some(Utc::now().naive_utc())); + + let invite_token = active_invite_token.update(&state.db).await?; + Ok(SuccessResponse::ok(invite_token.into())) +} + +#[utoipa::path( + patch, + path = "/update/expiration_date", + tag = INVITE_TOKEN, + summary = "Change expiration date", + description = "Change invite token expiration date", + request_body = ChangeInviteTokenExpirationDateRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the changed invite token data" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn update_expiration_date( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + let mut active_invite_token = get_owned_invite_token(req.id, user.id, &state.db) + .await? + .into_active_model(); + + active_invite_token.expiration_date = + Set(req.expiration_date.as_ref().map(DateTime::naive_utc)); + + let invite_token = active_invite_token.update(&state.db).await?; + Ok(SuccessResponse::ok(invite_token.into())) +} + +#[utoipa::path( + delete, + path = "/delete", + tag = INVITE_TOKEN, + summary = "Delete", + description = "Delete the invite token", + request_body = DeleteInviteTokenRequest, + responses( + ( + status = 200, body = SuccessResponse, + description = "Success response with the deleted invite token data" + ), + GlobalResponses + ), + security(("auth" = [])), +)] +async fn delete( + State(state): State, + Auth(user): Auth, + ApiJson(req): ApiJson, +) -> ApiResult { + let invite_token = get_owned_invite_token(req.id, user.id, &state.db).await?; + invite_token.clone().delete(&state.db).await?; + Ok(SuccessResponse::ok(invite_token.into())) +} pub fn router() -> OpenApiRouter { OpenApiRouter::new() + .routes(routes!(get_by_id)) + .routes(routes!(get_by_queue_id)) + .routes(routes!(create)) + .routes(routes!(expire)) + .routes(routes!(update_expiration_date)) + .routes(routes!(delete)) } -- cgit v1.2.3