feat: add utoipa path annotations to hackathon and QR handlers, register in swagger

All hackathon endpoints (/v1/hackathon/*) and QR endpoints (/v1/qr/*)
are now visible in the Swagger UI at /docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
maulanasdqn
2026-04-03 01:22:38 +07:00
co-authored by Claude Sonnet 4.6
parent 8144ab40e9
commit e1bc336baa
15 changed files with 722 additions and 3 deletions
@@ -15,6 +15,18 @@ use crate::qr::{
middleware::qr_auth::QrAuthUser,
};
#[utoipa::path(
post,
path = "/v1/qr/campaigns",
request_body = CreateCampaignRequest,
responses(
(status = 201, description = "Create a QR campaign"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Campaigns",
security(("bearer_auth" = []))
)]
pub async fn create_campaign_handler(
Extension(service): Extension<Arc<dyn QrCampaignService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -31,6 +43,17 @@ pub async fn create_campaign_handler(
Ok(imphnen_utils::response_format::ApiCreated(campaign).into_response())
}
#[utoipa::path(
get,
path = "/v1/qr/campaigns",
responses(
(status = 200, description = "Admin: list all QR campaigns"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Campaigns",
security(("bearer_auth" = []))
)]
pub async fn list_campaigns_handler(
Extension(service): Extension<Arc<dyn QrCampaignService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -44,6 +67,18 @@ pub async fn list_campaigns_handler(
Ok(ApiSuccess(campaigns).into_response())
}
#[utoipa::path(
put,
path = "/v1/qr/campaigns/{id}/activate",
params(("id" = Uuid, Path, description = "Campaign ID")),
responses(
(status = 200, description = "Admin: activate a campaign"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Campaigns",
security(("bearer_auth" = []))
)]
pub async fn activate_campaign_handler(
Extension(service): Extension<Arc<dyn QrCampaignService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -58,6 +93,18 @@ pub async fn activate_campaign_handler(
Ok(ApiSuccess(campaign).into_response())
}
#[utoipa::path(
delete,
path = "/v1/qr/campaigns/{id}",
params(("id" = Uuid, Path, description = "Campaign ID")),
responses(
(status = 200, description = "Admin: delete a campaign"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Campaigns",
security(("bearer_auth" = []))
)]
pub async fn delete_campaign_handler(
Extension(service): Extension<Arc<dyn QrCampaignService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -75,6 +122,16 @@ pub async fn delete_campaign_handler(
)
}
#[utoipa::path(
post,
path = "/v1/qr/campaigns/process-image",
responses(
(status = 200, description = "Process QR code image (multipart/form-data with 'file' field)"),
(status = 401, description = "Unauthorized")
),
tag = "QR - Campaigns",
security(("bearer_auth" = []))
)]
pub async fn process_image_handler(
Extension(service): Extension<Arc<dyn QrCampaignService>>,
Extension(_auth_user): Extension<QrAuthUser>,
@@ -15,6 +15,16 @@ use crate::qr::{
},
};
#[utoipa::path(
get,
path = "/v1/qr/users/me",
responses(
(status = 200, description = "Get my QR user profile"),
(status = 401, description = "Unauthorized")
),
tag = "QR - Users",
security(("bearer_auth" = []))
)]
pub async fn get_me_handler(
Extension(service): Extension<Arc<dyn QrUserService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -23,6 +33,17 @@ pub async fn get_me_handler(
Ok(ApiSuccess(user).into_response())
}
#[utoipa::path(
put,
path = "/v1/qr/users/me",
request_body = UpdateProfileRequest,
responses(
(status = 200, description = "Update my QR user profile"),
(status = 401, description = "Unauthorized")
),
tag = "QR - Users",
security(("bearer_auth" = []))
)]
pub async fn update_me_handler(
Extension(service): Extension<Arc<dyn QrUserService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -36,6 +57,17 @@ pub async fn update_me_handler(
Ok(ApiSuccess(user).into_response())
}
#[utoipa::path(
get,
path = "/v1/qr/users",
responses(
(status = 200, description = "Admin: list all QR users"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Users",
security(("bearer_auth" = []))
)]
pub async fn list_users_handler(
Extension(service): Extension<Arc<dyn QrUserService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -49,6 +81,19 @@ pub async fn list_users_handler(
Ok(ApiSuccess(users).into_response())
}
#[utoipa::path(
put,
path = "/v1/qr/users/{id}/role",
params(("id" = Uuid, Path, description = "User ID")),
request_body = UpdateRoleRequest,
responses(
(status = 200, description = "Admin: update user role"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Users",
security(("bearer_auth" = []))
)]
pub async fn update_role_handler(
Extension(service): Extension<Arc<dyn QrUserService>>,
Extension(auth_user): Extension<QrAuthUser>,
@@ -64,6 +109,18 @@ pub async fn update_role_handler(
Ok(ApiSuccess(user).into_response())
}
#[utoipa::path(
delete,
path = "/v1/qr/users/{id}",
params(("id" = Uuid, Path, description = "User ID")),
responses(
(status = 200, description = "Admin: delete QR user"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "QR - Users",
security(("bearer_auth" = []))
)]
pub async fn delete_user_handler(
Extension(service): Extension<Arc<dyn QrUserService>>,
Extension(auth_user): Extension<QrAuthUser>,
+112
View File
@@ -3,6 +3,12 @@ use imphnen_cms::events::infrastructure::http::dto::{
EventsDetailItemDto, EventsListItemDto,
};
use imphnen_cms::events::infrastructure::http::handlers as events_controller;
use imphnen_cms::qr::campaigns::infrastructure::http::dto::CreateCampaignRequest;
use imphnen_cms::qr::campaigns::infrastructure::http::handlers as qr_campaigns_controller;
use imphnen_cms::qr::users::infrastructure::http::dto::{
UpdateProfileRequest, UpdateRoleRequest,
};
use imphnen_cms::qr::users::infrastructure::http::handlers as qr_users_controller;
use imphnen_cms::testimonials::infrastructure::http::dto::{
TestimonialsCreateRequestDto, TestimonialsDetailItemDto, TestimonialsListItemDto,
TestimonialsUpdateRequestDto,
@@ -41,6 +47,46 @@ use imphnen_gacha::gacha_rolls::infrastructure::http::dto::{
GachaRollCreateRequestDto, GachaRollItemDto,
};
use imphnen_gacha::gacha_rolls::infrastructure::http::handlers as gacha_rolls_controller;
use imphnen_hackathon::admin::domain::entity::{
AdminSubmissionRow, AdminTeamRow, AdminUserRow, WinnerRow,
};
use imphnen_hackathon::admin::infrastructure::http::dto::{
SetAdminRequest, SetWinnerRequest,
};
use imphnen_hackathon::admin::infrastructure::http::handlers as hackathon_admin_controller;
use imphnen_hackathon::certificates::infrastructure::http::dto::CertificateResponse;
use imphnen_hackathon::certificates::infrastructure::http::handlers as hackathon_certificates_controller;
use imphnen_hackathon::chat::infrastructure::http::dto::{
MessageResponse, SendMessageRequest,
};
use imphnen_hackathon::chat::infrastructure::http::handlers as hackathon_chat_controller;
use imphnen_hackathon::invitations::infrastructure::http::dto::{
CreateInvitationRequest, InvitationResponse, RespondToInvitationRequest,
};
use imphnen_hackathon::invitations::infrastructure::http::handlers as hackathon_invitations_controller;
use imphnen_hackathon::join_requests::infrastructure::http::dto::{
CreateJoinRequestRequest, JoinRequestResponse, RespondToJoinRequestRequest,
};
use imphnen_hackathon::join_requests::infrastructure::http::handlers as hackathon_join_requests_controller;
use imphnen_hackathon::storage::infrastructure::http::dto::{
UploadRequest, UploadResponse,
};
use imphnen_hackathon::storage::infrastructure::http::handlers as hackathon_storage_controller;
use imphnen_hackathon::submissions::infrastructure::http::dto::{
CreateSubmissionRequest, SubmissionResponse, UpdateSubmissionRequest,
};
use imphnen_hackathon::submissions::infrastructure::http::handlers as hackathon_submissions_controller;
use imphnen_hackathon::teams::infrastructure::http::dto::{
BrowseTeamsQuery, CreateTeamRequest, TeamListResponse, TeamMemberResponse,
TeamResponse, UpdateTeamRequest, UserInfoResponse,
};
use imphnen_hackathon::teams::infrastructure::http::handlers as hackathon_teams_controller;
use imphnen_hackathon::users::infrastructure::http::dto::{
UpdateUserRequest, UserResponse,
};
use imphnen_hackathon::users::infrastructure::http::handlers as hackathon_users_controller;
use imphnen_hackathon::winners::infrastructure::http::dto::WinnerResponse;
use imphnen_hackathon::winners::infrastructure::http::handlers as hackathon_winners_controller;
use imphnen_iam::auth::infrastructure::http::dto::{
AuthLoginRequestDto, AuthLoginResponsetDto, AuthNewPasswordRequestDto,
AuthRefreshTokenRequestDto, AuthResendOtpRequestDto, AuthVerifyEmailRequestDto,
@@ -102,6 +148,48 @@ use utoipa::OpenApi;
sessions_controller::mutation_handlers::post_book_session, sessions_controller::query_handlers::get_mentor_sessions,
sessions_controller::query_handlers::get_mentor_availability, sessions_controller::mutation_handlers::put_update_session_status,
sessions_controller::mutation_handlers::post_submit_feedback, sessions_controller::query_handlers::get_my_sessions,
hackathon_users_controller::get_me_handler, hackathon_users_controller::update_me_handler,
hackathon_users_controller::get_user_handler, hackathon_users_controller::get_user_teams_handler,
hackathon_teams_controller::create_team_handler, hackathon_teams_controller::get_team_handler,
hackathon_teams_controller::browse_teams_handler, hackathon_teams_controller::get_my_teams_handler,
hackathon_teams_controller::update_team_handler, hackathon_teams_controller::delete_team_handler,
hackathon_teams_controller::leave_team_handler, hackathon_teams_controller::remove_member_handler,
hackathon_invitations_controller::get_my_invitations_handler,
hackathon_invitations_controller::respond_to_invitation_handler,
hackathon_invitations_controller::invite_team_member_handler,
hackathon_join_requests_controller::create_join_request_handler,
hackathon_join_requests_controller::get_my_join_requests_handler,
hackathon_join_requests_controller::get_team_join_requests_handler,
hackathon_join_requests_controller::respond_to_join_request_handler,
hackathon_submissions_controller::create_submission_handler,
hackathon_submissions_controller::get_team_submission_handler,
hackathon_submissions_controller::update_submission_handler,
hackathon_submissions_controller::submit_project_handler,
hackathon_submissions_controller::confirm_submission_handler,
hackathon_submissions_controller::cancel_submission_handler,
hackathon_certificates_controller::get_certificate_handler,
hackathon_winners_controller::list_winners_handler,
hackathon_admin_controller::admin_list_users, hackathon_admin_controller::admin_get_user,
hackathon_admin_controller::admin_set_admin, hackathon_admin_controller::admin_delete_user,
hackathon_admin_controller::admin_list_teams, hackathon_admin_controller::admin_delete_team,
hackathon_admin_controller::admin_list_submissions,
hackathon_admin_controller::admin_set_winner, hackathon_admin_controller::admin_remove_winner,
hackathon_admin_controller::admin_list_winners,
hackathon_chat_controller::get_team_messages_handler,
hackathon_chat_controller::send_message_handler,
hackathon_chat_controller::delete_message_handler,
hackathon_storage_controller::upload_file_handler,
hackathon_storage_controller::upload_avatar_handler,
hackathon_storage_controller::upload_team_handler,
hackathon_storage_controller::upload_submission_handler,
qr_users_controller::get_me_handler, qr_users_controller::update_me_handler,
qr_users_controller::list_users_handler, qr_users_controller::update_role_handler,
qr_users_controller::delete_user_handler,
qr_campaigns_controller::create_campaign_handler,
qr_campaigns_controller::list_campaigns_handler,
qr_campaigns_controller::activate_campaign_handler,
qr_campaigns_controller::delete_campaign_handler,
qr_campaigns_controller::process_image_handler,
),
components(schemas(
MessageResponseDto, AuthLoginRequestDto, AuthLoginResponsetDto,
@@ -135,6 +223,18 @@ use utoipa::OpenApi;
ResponseSuccessDto<BookSessionResponseDto>, ResponseSuccessDto<SessionListResponseDto>,
ResponseSuccessDto<MentorAvailabilityDto>, ResponseSuccessDto<UpdateSessionStatusResponseDto>,
ResponseSuccessDto<SessionFeedbackResponseDto>,
UserResponse, UpdateUserRequest,
TeamResponse, CreateTeamRequest, UpdateTeamRequest, BrowseTeamsQuery,
TeamListResponse, UserInfoResponse, TeamMemberResponse,
InvitationResponse, RespondToInvitationRequest, CreateInvitationRequest,
JoinRequestResponse, CreateJoinRequestRequest, RespondToJoinRequestRequest,
SubmissionResponse, CreateSubmissionRequest, UpdateSubmissionRequest,
CertificateResponse, WinnerResponse,
SetAdminRequest, SetWinnerRequest,
AdminUserRow, AdminTeamRow, AdminSubmissionRow, WinnerRow,
MessageResponse, SendMessageRequest,
UploadRequest, UploadResponse,
UpdateProfileRequest, UpdateRoleRequest, CreateCampaignRequest,
)),
info(
title = "IMPHNEN Backend Service",
@@ -155,6 +255,18 @@ use utoipa::OpenApi;
(name = "Mentors - Admin", description = "Dimentorin — Mentor admin endpoints (/v1/dimentorin/mentors)"),
(name = "sessions", description = "Dimentorin — Session management (/v1/dimentorin/sessions)"),
(name = "Gacha", description = "Gacha system (/v1/gacha)"),
(name = "Hackathon - Users", description = "Hackathon — User profile (/v1/hackathon/users)"),
(name = "Hackathon - Teams", description = "Hackathon — Team management (/v1/hackathon/teams)"),
(name = "Hackathon - Invitations", description = "Hackathon — Team invitations (/v1/hackathon/invitations)"),
(name = "Hackathon - Join Requests", description = "Hackathon — Join requests (/v1/hackathon/join-requests)"),
(name = "Hackathon - Submissions", description = "Hackathon — Project submissions (/v1/hackathon/submissions)"),
(name = "Hackathon - Certificates", description = "Hackathon — Certificates (/v1/hackathon/certificates)"),
(name = "Hackathon - Winners", description = "Hackathon — Winners (/v1/hackathon/winners)"),
(name = "Hackathon - Admin", description = "Hackathon — Admin management (/v1/hackathon/admin)"),
(name = "Hackathon - Chat", description = "Hackathon — Team chat (/v1/hackathon/chat)"),
(name = "Hackathon - Storage", description = "Hackathon — File uploads (/v1/hackathon/upload)"),
(name = "QR - Users", description = "QR — User management (/v1/qr/users)"),
(name = "QR - Campaigns", description = "QR — Campaign management (/v1/qr/campaigns)"),
)
)]
pub struct ApiDoc;
@@ -1,8 +1,8 @@
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use utoipa::{IntoParams, ToSchema};
use uuid::Uuid;
#[derive(Deserialize)]
#[derive(Deserialize, IntoParams)]
pub struct PageQuery {
#[serde(default = "default_page")]
pub page: i64,
@@ -12,6 +12,18 @@ use imphnen_utils::{
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
get,
path = "/v1/hackathon/admin/users",
params(PageQuery),
responses(
(status = 200, description = "Admin: list all users"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_list_users(
Extension(service): Extension<Arc<dyn AdminService>>,
Query(q): Query<PageQuery>,
@@ -28,6 +40,18 @@ pub async fn admin_list_users(
)
}
#[utoipa::path(
get,
path = "/v1/hackathon/admin/users/{user_id}",
params(("user_id" = Uuid, Path, description = "User ID")),
responses(
(status = 200, description = "Admin: get user by ID"),
(status = 403, description = "Forbidden - admin only"),
(status = 404, description = "User not found")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_get_user(
Extension(service): Extension<Arc<dyn AdminService>>,
Path(user_id): Path<Uuid>,
@@ -36,6 +60,18 @@ pub async fn admin_get_user(
Ok(ApiSuccess(user).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/admin/users/{user_id}/set-admin",
params(("user_id" = Uuid, Path, description = "User ID")),
request_body = SetAdminRequest,
responses(
(status = 200, description = "Admin: set user admin status"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_set_admin(
Extension(service): Extension<Arc<dyn AdminService>>,
Path(user_id): Path<Uuid>,
@@ -45,6 +81,17 @@ pub async fn admin_set_admin(
Ok(ApiMessage::ok("User admin status updated"))
}
#[utoipa::path(
delete,
path = "/v1/hackathon/admin/users/{user_id}",
params(("user_id" = Uuid, Path, description = "User ID")),
responses(
(status = 200, description = "Admin: delete user"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_delete_user(
Extension(service): Extension<Arc<dyn AdminService>>,
Path(user_id): Path<Uuid>,
@@ -53,6 +100,17 @@ pub async fn admin_delete_user(
Ok(ApiMessage::ok("User deleted"))
}
#[utoipa::path(
get,
path = "/v1/hackathon/admin/teams",
params(PageQuery),
responses(
(status = 200, description = "Admin: list all teams"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_list_teams(
Extension(service): Extension<Arc<dyn AdminService>>,
Query(q): Query<PageQuery>,
@@ -69,6 +127,17 @@ pub async fn admin_list_teams(
)
}
#[utoipa::path(
delete,
path = "/v1/hackathon/admin/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Admin: delete team"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_delete_team(
Extension(service): Extension<Arc<dyn AdminService>>,
Path(team_id): Path<Uuid>,
@@ -77,6 +146,17 @@ pub async fn admin_delete_team(
Ok(ApiMessage::ok("Team deleted"))
}
#[utoipa::path(
get,
path = "/v1/hackathon/admin/submissions",
params(PageQuery),
responses(
(status = 200, description = "Admin: list all submissions"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_list_submissions(
Extension(service): Extension<Arc<dyn AdminService>>,
Query(q): Query<PageQuery>,
@@ -93,6 +173,17 @@ pub async fn admin_list_submissions(
)
}
#[utoipa::path(
post,
path = "/v1/hackathon/admin/winners",
request_body = SetWinnerRequest,
responses(
(status = 200, description = "Admin: set winner"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_set_winner(
Extension(service): Extension<Arc<dyn AdminService>>,
Json(body): Json<SetWinnerRequest>,
@@ -103,6 +194,17 @@ pub async fn admin_set_winner(
Ok(ApiMessage::ok("Winner set"))
}
#[utoipa::path(
delete,
path = "/v1/hackathon/admin/winners/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Admin: remove winner"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_remove_winner(
Extension(service): Extension<Arc<dyn AdminService>>,
Path(team_id): Path<Uuid>,
@@ -111,6 +213,16 @@ pub async fn admin_remove_winner(
Ok(ApiMessage::ok("Winner removed"))
}
#[utoipa::path(
get,
path = "/v1/hackathon/admin/winners",
responses(
(status = 200, description = "Admin: list winners"),
(status = 403, description = "Forbidden - admin only")
),
tag = "Hackathon - Admin",
security(("bearer_auth" = []))
)]
pub async fn admin_list_winners(
Extension(service): Extension<Arc<dyn AdminService>>,
) -> Result<axum::response::Response, AppError> {
@@ -5,6 +5,16 @@ use imphnen_utils::{errors::AppError, response_format::ApiSuccess};
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
get,
path = "/v1/hackathon/certificates/{user_id}",
params(("user_id" = Uuid, Path, description = "User ID")),
responses(
(status = 200, description = "Get certificate for user"),
(status = 404, description = "Certificate not found")
),
tag = "Hackathon - Certificates"
)]
pub async fn get_certificate_handler(
Extension(service): Extension<Arc<dyn CertificateService>>,
Path(user_id): Path<Uuid>,
@@ -9,6 +9,17 @@ use imphnen_utils::{
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
get,
path = "/v1/hackathon/chat/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Get team chat messages"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Chat",
security(("bearer_auth" = []))
)]
pub async fn get_team_messages_handler(
Extension(service): Extension<Arc<dyn ChatService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -20,6 +31,18 @@ pub async fn get_team_messages_handler(
Ok(ApiSuccess(response).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/chat/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
request_body = SendMessageRequest,
responses(
(status = 200, description = "Send a message to team chat"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Chat",
security(("bearer_auth" = []))
)]
pub async fn send_message_handler(
Extension(service): Extension<Arc<dyn ChatService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -32,6 +55,18 @@ pub async fn send_message_handler(
Ok(ApiSuccess(MessageResponse::from(message)).into_response())
}
#[utoipa::path(
delete,
path = "/v1/hackathon/chat/messages/{message_id}",
params(("message_id" = Uuid, Path, description = "Message ID")),
responses(
(status = 200, description = "Delete a chat message"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Chat",
security(("bearer_auth" = []))
)]
pub async fn delete_message_handler(
Extension(service): Extension<Arc<dyn ChatService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -9,6 +9,16 @@ use imphnen_utils::{
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
get,
path = "/v1/hackathon/invitations/my",
responses(
(status = 200, description = "Get my invitations"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Invitations",
security(("bearer_auth" = []))
)]
pub async fn get_my_invitations_handler(
Extension(service): Extension<Arc<dyn InvitationService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -19,6 +29,19 @@ pub async fn get_my_invitations_handler(
Ok(ApiSuccess(response).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/invitations/{invitation_id}/respond",
params(("invitation_id" = Uuid, Path, description = "Invitation ID")),
request_body = RespondToInvitationRequest,
responses(
(status = 200, description = "Respond to invitation"),
(status = 401, description = "Unauthorized"),
(status = 404, description = "Invitation not found")
),
tag = "Hackathon - Invitations",
security(("bearer_auth" = []))
)]
pub async fn respond_to_invitation_handler(
Extension(service): Extension<Arc<dyn InvitationService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -36,6 +59,19 @@ pub async fn respond_to_invitation_handler(
Ok(ApiMessage::ok(msg).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/invitations/teams/{team_id}/invite",
params(("team_id" = Uuid, Path, description = "Team ID")),
request_body = CreateInvitationRequest,
responses(
(status = 200, description = "Invite a member to team"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Invitations",
security(("bearer_auth" = []))
)]
pub async fn invite_team_member_handler(
Extension(service): Extension<Arc<dyn InvitationService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -9,6 +9,18 @@ use imphnen_utils::{
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
post,
path = "/v1/hackathon/join-requests/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
request_body = CreateJoinRequestRequest,
responses(
(status = 200, description = "Create a join request"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Join Requests",
security(("bearer_auth" = []))
)]
pub async fn create_join_request_handler(
Extension(service): Extension<Arc<dyn JoinRequestService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -21,6 +33,16 @@ pub async fn create_join_request_handler(
Ok(ApiSuccess(JoinRequestResponse::from(request)).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/join-requests/my",
responses(
(status = 200, description = "Get my join requests"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Join Requests",
security(("bearer_auth" = []))
)]
pub async fn get_my_join_requests_handler(
Extension(service): Extension<Arc<dyn JoinRequestService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -31,6 +53,18 @@ pub async fn get_my_join_requests_handler(
Ok(ApiSuccess(response).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/join-requests/teams/{team_id}/pending",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Get pending join requests for team"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Join Requests",
security(("bearer_auth" = []))
)]
pub async fn get_team_join_requests_handler(
Extension(service): Extension<Arc<dyn JoinRequestService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -44,6 +78,19 @@ pub async fn get_team_join_requests_handler(
Ok(ApiSuccess(response).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/join-requests/{request_id}/respond",
params(("request_id" = Uuid, Path, description = "Join request ID")),
request_body = RespondToJoinRequestRequest,
responses(
(status = 200, description = "Respond to join request"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Join Requests",
security(("bearer_auth" = []))
)]
pub async fn respond_to_join_request_handler(
Extension(service): Extension<Arc<dyn JoinRequestService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -5,6 +5,17 @@ use axum::{Extension, Json, response::IntoResponse};
use imphnen_utils::{errors::AppError, response_format::ApiSuccess};
use std::sync::Arc;
#[utoipa::path(
post,
path = "/v1/hackathon/upload",
request_body = UploadRequest,
responses(
(status = 200, description = "Upload a file"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Storage",
security(("bearer_auth" = []))
)]
pub async fn upload_file_handler(
Extension(service): Extension<Arc<dyn StorageService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -22,6 +33,17 @@ pub async fn upload_file_handler(
Ok(ApiSuccess(UploadResponse { url }).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/upload/avatar",
request_body = UploadRequest,
responses(
(status = 200, description = "Upload avatar image"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Storage",
security(("bearer_auth" = []))
)]
pub async fn upload_avatar_handler(
Extension(service): Extension<Arc<dyn StorageService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -39,6 +61,17 @@ pub async fn upload_avatar_handler(
Ok(ApiSuccess(UploadResponse { url }).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/upload/team",
request_body = UploadRequest,
responses(
(status = 200, description = "Upload team image"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Storage",
security(("bearer_auth" = []))
)]
pub async fn upload_team_handler(
Extension(service): Extension<Arc<dyn StorageService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -56,6 +89,17 @@ pub async fn upload_team_handler(
Ok(ApiSuccess(UploadResponse { url }).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/upload/submission",
request_body = UploadRequest,
responses(
(status = 200, description = "Upload submission file"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Storage",
security(("bearer_auth" = []))
)]
pub async fn upload_submission_handler(
Extension(service): Extension<Arc<dyn StorageService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -6,6 +6,18 @@ use imphnen_utils::{errors::AppError, response_format::ApiSuccess};
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
post,
path = "/v1/hackathon/submissions/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
request_body = CreateSubmissionRequest,
responses(
(status = 200, description = "Create submission for team"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Submissions",
security(("bearer_auth" = []))
)]
pub async fn create_submission_handler(
Extension(service): Extension<Arc<dyn SubmissionService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -18,6 +30,18 @@ pub async fn create_submission_handler(
Ok(ApiSuccess(SubmissionResponse::from(sub)).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/submissions/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Get team submission"),
(status = 401, description = "Unauthorized"),
(status = 404, description = "Not found")
),
tag = "Hackathon - Submissions",
security(("bearer_auth" = []))
)]
pub async fn get_team_submission_handler(
Extension(service): Extension<Arc<dyn SubmissionService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -27,6 +51,18 @@ pub async fn get_team_submission_handler(
Ok(ApiSuccess(SubmissionResponse::from(sub)).into_response())
}
#[utoipa::path(
put,
path = "/v1/hackathon/submissions/{submission_id}",
params(("submission_id" = Uuid, Path, description = "Submission ID")),
request_body = UpdateSubmissionRequest,
responses(
(status = 200, description = "Update submission"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Submissions",
security(("bearer_auth" = []))
)]
pub async fn update_submission_handler(
Extension(service): Extension<Arc<dyn SubmissionService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -39,6 +75,17 @@ pub async fn update_submission_handler(
Ok(ApiSuccess(SubmissionResponse::from(sub)).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/submissions/{submission_id}/submit",
params(("submission_id" = Uuid, Path, description = "Submission ID")),
responses(
(status = 200, description = "Submit project"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Submissions",
security(("bearer_auth" = []))
)]
pub async fn submit_project_handler(
Extension(service): Extension<Arc<dyn SubmissionService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -48,6 +95,17 @@ pub async fn submit_project_handler(
Ok(ApiSuccess(SubmissionResponse::from(sub)).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/submissions/{submission_id}/confirm",
params(("submission_id" = Uuid, Path, description = "Submission ID")),
responses(
(status = 200, description = "Confirm submission"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Submissions",
security(("bearer_auth" = []))
)]
pub async fn confirm_submission_handler(
Extension(service): Extension<Arc<dyn SubmissionService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -59,6 +117,17 @@ pub async fn confirm_submission_handler(
Ok(ApiSuccess(SubmissionResponse::from(sub)).into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/submissions/{submission_id}/cancel",
params(("submission_id" = Uuid, Path, description = "Submission ID")),
responses(
(status = 200, description = "Cancel submission"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Submissions",
security(("bearer_auth" = []))
)]
pub async fn cancel_submission_handler(
Extension(service): Extension<Arc<dyn SubmissionService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -145,7 +145,7 @@ impl From<UpdateTeamRequest> for UpdateTeamInput {
}
}
#[derive(Debug, Deserialize, ToSchema)]
#[derive(Debug, Deserialize, ToSchema, utoipa::IntoParams)]
pub struct BrowseTeamsQuery {
pub search: Option<String>,
pub city: Option<String>,
@@ -13,6 +13,17 @@ use imphnen_utils::{
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
post,
path = "/v1/hackathon/teams",
request_body = CreateTeamRequest,
responses(
(status = 200, description = "Create a new team"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Teams",
security(("bearer_auth" = []))
)]
pub async fn create_team_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -22,6 +33,16 @@ pub async fn create_team_handler(
Ok(ApiSuccess(TeamResponse::from(team)).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Get team by ID"),
(status = 404, description = "Team not found")
),
tag = "Hackathon - Teams"
)]
pub async fn get_team_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Path(team_id): Path<Uuid>,
@@ -30,6 +51,15 @@ pub async fn get_team_handler(
Ok(ApiSuccess(TeamResponse::from(team)).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/teams/browse",
params(BrowseTeamsQuery),
responses(
(status = 200, description = "Browse teams with filters")
),
tag = "Hackathon - Teams"
)]
pub async fn browse_teams_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Query(query): Query<BrowseTeamsQuery>,
@@ -46,6 +76,16 @@ pub async fn browse_teams_handler(
)
}
#[utoipa::path(
get,
path = "/v1/hackathon/teams/my",
responses(
(status = 200, description = "Get my teams"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Teams",
security(("bearer_auth" = []))
)]
pub async fn get_my_teams_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -62,6 +102,19 @@ pub async fn get_my_teams_handler(
)
}
#[utoipa::path(
put,
path = "/v1/hackathon/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
request_body = UpdateTeamRequest,
responses(
(status = 200, description = "Update team"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Teams",
security(("bearer_auth" = []))
)]
pub async fn update_team_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -74,6 +127,18 @@ pub async fn update_team_handler(
Ok(ApiSuccess(TeamResponse::from(team)).into_response())
}
#[utoipa::path(
delete,
path = "/v1/hackathon/teams/{team_id}",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Delete team"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Teams",
security(("bearer_auth" = []))
)]
pub async fn delete_team_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -83,6 +148,17 @@ pub async fn delete_team_handler(
Ok(ApiMessage::ok("Team deleted successfully").into_response())
}
#[utoipa::path(
post,
path = "/v1/hackathon/teams/{team_id}/leave",
params(("team_id" = Uuid, Path, description = "Team ID")),
responses(
(status = 200, description = "Leave team"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Teams",
security(("bearer_auth" = []))
)]
pub async fn leave_team_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -92,6 +168,21 @@ pub async fn leave_team_handler(
Ok(ApiMessage::ok("Left team successfully").into_response())
}
#[utoipa::path(
delete,
path = "/v1/hackathon/teams/{team_id}/members/{member_id}",
params(
("team_id" = Uuid, Path, description = "Team ID"),
("member_id" = Uuid, Path, description = "Member user ID")
),
responses(
(status = 200, description = "Remove team member"),
(status = 401, description = "Unauthorized"),
(status = 403, description = "Forbidden")
),
tag = "Hackathon - Teams",
security(("bearer_auth" = []))
)]
pub async fn remove_member_handler(
Extension(service): Extension<Arc<dyn TeamService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -6,6 +6,16 @@ use imphnen_utils::{errors::AppError, response_format::ApiSuccess};
use std::sync::Arc;
use uuid::Uuid;
#[utoipa::path(
get,
path = "/v1/hackathon/users/me",
responses(
(status = 200, description = "Get my hackathon user profile"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Users",
security(("bearer_auth" = []))
)]
pub async fn get_me_handler(
Extension(service): Extension<Arc<dyn HackathonUserService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -14,6 +24,17 @@ pub async fn get_me_handler(
Ok(ApiSuccess(UserResponse::from(user)).into_response())
}
#[utoipa::path(
put,
path = "/v1/hackathon/users/me",
request_body = UpdateUserRequest,
responses(
(status = 200, description = "Update my hackathon user profile"),
(status = 401, description = "Unauthorized")
),
tag = "Hackathon - Users",
security(("bearer_auth" = []))
)]
pub async fn update_me_handler(
Extension(service): Extension<Arc<dyn HackathonUserService>>,
Extension(auth): Extension<HackathonAuthUser>,
@@ -23,6 +44,16 @@ pub async fn update_me_handler(
Ok(ApiSuccess(UserResponse::from(user)).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/users/{user_id}",
params(("user_id" = Uuid, Path, description = "User ID")),
responses(
(status = 200, description = "Get hackathon user by ID"),
(status = 404, description = "User not found")
),
tag = "Hackathon - Users"
)]
pub async fn get_user_handler(
Extension(service): Extension<Arc<dyn HackathonUserService>>,
Path(user_id): Path<Uuid>,
@@ -31,6 +62,16 @@ pub async fn get_user_handler(
Ok(ApiSuccess(UserResponse::from(user)).into_response())
}
#[utoipa::path(
get,
path = "/v1/hackathon/users/{user_id}/teams",
params(("user_id" = Uuid, Path, description = "User ID")),
responses(
(status = 200, description = "Get teams for a hackathon user"),
(status = 404, description = "User not found")
),
tag = "Hackathon - Users"
)]
pub async fn get_user_teams_handler(
Extension(service): Extension<Arc<dyn HackathonUserService>>,
Path(user_id): Path<Uuid>,
@@ -4,6 +4,14 @@ use axum::{Extension, response::IntoResponse};
use imphnen_utils::{errors::AppError, response_format::ApiSuccess};
use std::sync::Arc;
#[utoipa::path(
get,
path = "/v1/hackathon/winners",
responses(
(status = 200, description = "List hackathon winners")
),
tag = "Hackathon - Winners"
)]
pub async fn list_winners_handler(
Extension(service): Extension<Arc<dyn WinnerService>>,
) -> Result<axum::response::Response, AppError> {