feat: Update hackathon event and submission routes to require admin permissions and adjust response descriptions

This commit is contained in:
MythEclipse
2025-10-27 17:26:53 +07:00
parent d5ccf4cf75
commit e77797d7bb
3 changed files with 66 additions and 38 deletions
@@ -176,16 +176,20 @@ pub async fn delete_hackathon(
// Hackathon Events routes
#[utoipa::path(
post,
security(
("Bearer" = [])
),
path = "/v1/hackathons/{hackathon_id}/events",
params(
("hackathon_id" = String, Path, description = "Hackathon ID")
),
request_body = HackathonEventCreateRequestDto,
responses(
(status = 201, description = "[PUBLIC] Event created successfully", body = ResponseSuccessDto<HackathonEventDto>),
(status = 400, description = "[PUBLIC] Bad request", body = ErrorDto),
(status = 404, description = "[PUBLIC] Hackathon not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 201, description = "[ADMIN] Event created successfully", body = ResponseSuccessDto<HackathonEventDto>),
(status = 400, description = "[ADMIN] Bad request", body = ErrorDto),
(status = 403, description = "[ADMIN] Forbidden - Administrator permission required", body = ErrorDto),
(status = 404, description = "[ADMIN] Hackathon not found", body = ErrorDto),
(status = 500, description = "[ADMIN] Internal server error", body = ErrorDto)
),
tag = "Hackathon Events"
)]
@@ -232,16 +236,20 @@ pub async fn list_hackathon_events(
#[utoipa::path(
put,
security(
("Bearer" = [])
),
path = "/v1/hackathons/events/{id}",
params(
("id" = String, Path, description = "Event ID")
),
request_body = HackathonEventUpdateRequestDto,
responses(
(status = 200, description = "[PUBLIC] Event updated successfully", body = ResponseSuccessDto<HackathonEventDto>),
(status = 400, description = "[PUBLIC] Bad request", body = ErrorDto),
(status = 404, description = "[PUBLIC] Event not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 200, description = "[ADMIN] Event updated successfully", body = ResponseSuccessDto<HackathonEventDto>),
(status = 400, description = "[ADMIN] Bad request", body = ErrorDto),
(status = 403, description = "[ADMIN] Forbidden - Administrator permission required", body = ErrorDto),
(status = 404, description = "[ADMIN] Event not found", body = ErrorDto),
(status = 500, description = "[ADMIN] Internal server error", body = ErrorDto)
),
tag = "Hackathon Events"
)]
@@ -258,14 +266,18 @@ pub async fn update_hackathon_event(
#[utoipa::path(
delete,
security(
("Bearer" = [])
),
path = "/v1/hackathons/events/{id}",
params(
("id" = String, Path, description = "Event ID")
),
responses(
(status = 200, description = "[PUBLIC] Event deleted successfully", body = ResponseSuccessDto<String>),
(status = 404, description = "[PUBLIC] Event not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 200, description = "[ADMIN] Event deleted successfully", body = ResponseSuccessDto<String>),
(status = 403, description = "[ADMIN] Forbidden - Administrator permission required", body = ErrorDto),
(status = 404, description = "[ADMIN] Event not found", body = ErrorDto),
(status = 500, description = "[ADMIN] Internal server error", body = ErrorDto)
),
tag = "Hackathon Events"
)]
@@ -400,6 +412,9 @@ pub async fn delete_hackathon_timeline(
// Hackathon Submissions routes with timeline enforcement
#[utoipa::path(
post,
security(
("Bearer" = [])
),
path = "/v1/hackathons/{hackathon_id}/teams/{team_id}/submissions",
params(
("hackathon_id" = String, Path, description = "Hackathon ID"),
@@ -407,11 +422,12 @@ pub async fn delete_hackathon_timeline(
),
request_body = HackathonSubmissionCreateRequestDto,
responses(
(status = 201, description = "[PUBLIC] Submission created successfully", body = ResponseSuccessDto<HackathonSubmissionDto>),
(status = 400, description = "[PUBLIC] Bad request", body = ErrorDto),
(status = 403, description = "[PUBLIC] Forbidden - Submissions only allowed during submission phase", body = ErrorDto),
(status = 404, description = "[PUBLIC] Hackathon not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 201, description = "[AUTH] Submission created successfully", body = ResponseSuccessDto<HackathonSubmissionDto>),
(status = 400, description = "[AUTH] Bad request", body = ErrorDto),
(status = 401, description = "[AUTH] Unauthorized", body = ErrorDto),
(status = 403, description = "[AUTH] Forbidden - Submissions only allowed during submission phase", body = ErrorDto),
(status = 404, description = "[AUTH] Hackathon not found", body = ErrorDto),
(status = 500, description = "[AUTH] Internal server error", body = ErrorDto)
),
tag = "Hackathon Submissions"
)]
@@ -529,16 +545,20 @@ pub async fn get_hackathon_submission(
#[utoipa::path(
put,
security(
("Bearer" = [])
),
path = "/v1/hackathons/submissions/{id}",
params(
("id" = String, Path, description = "Submission ID")
),
request_body = HackathonSubmissionUpdateRequestDto,
responses(
(status = 200, description = "[PUBLIC] Submission updated successfully", body = ResponseSuccessDto<HackathonSubmissionDto>),
(status = 400, description = "[PUBLIC] Bad request", body = ErrorDto),
(status = 404, description = "[PUBLIC] Submission not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 200, description = "[AUTH] Submission updated successfully", body = ResponseSuccessDto<HackathonSubmissionDto>),
(status = 400, description = "[AUTH] Bad request", body = ErrorDto),
(status = 401, description = "[AUTH] Unauthorized", body = ErrorDto),
(status = 404, description = "[AUTH] Submission not found", body = ErrorDto),
(status = 500, description = "[AUTH] Internal server error", body = ErrorDto)
),
tag = "Hackathon Submissions"
)]
@@ -555,15 +575,19 @@ pub async fn update_hackathon_submission(
#[utoipa::path(
post,
security(
("Bearer" = [])
),
path = "/v1/hackathons/submissions/{id}/submit",
params(
("id" = String, Path, description = "Submission ID")
),
responses(
(status = 200, description = "[PUBLIC] Submission submitted successfully", body = ResponseSuccessDto<HackathonSubmissionDto>),
(status = 403, description = "[PUBLIC] Forbidden - Submissions only allowed during submission phase", body = ErrorDto),
(status = 404, description = "[PUBLIC] Submission not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 200, description = "[AUTH] Submission submitted successfully", body = ResponseSuccessDto<HackathonSubmissionDto>),
(status = 401, description = "[AUTH] Unauthorized", body = ErrorDto),
(status = 403, description = "[AUTH] Forbidden - Submissions only allowed during submission phase", body = ErrorDto),
(status = 404, description = "[AUTH] Submission not found", body = ErrorDto),
(status = 500, description = "[AUTH] Internal server error", body = ErrorDto)
),
tag = "Hackathon Submissions"
)]
@@ -581,14 +605,18 @@ pub async fn submit_hackathon_submission(
#[utoipa::path(
delete,
security(
("Bearer" = [])
),
path = "/v1/hackathons/submissions/{id}",
params(
("id" = String, Path, description = "Submission ID")
),
responses(
(status = 200, description = "[PUBLIC] Submission deleted successfully", body = ResponseSuccessDto<String>),
(status = 404, description = "[PUBLIC] Submission not found", body = ErrorDto),
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
(status = 200, description = "[AUTH] Submission deleted successfully", body = ResponseSuccessDto<String>),
(status = 401, description = "[AUTH] Unauthorized", body = ErrorDto),
(status = 404, description = "[AUTH] Submission not found", body = ErrorDto),
(status = 500, description = "[AUTH] Internal server error", body = ErrorDto)
),
tag = "Hackathon Submissions"
)]
+1 -1
View File
@@ -50,7 +50,7 @@ test_invalid_token_access() {
test_api_endpoint "GET User Me with Invalid Token" "GET" "/v1/users/me" 401 "" true
# Test with malformed token
AUTH_TOKEN="Bearer.malformed.token"
AUTH_TOKEN="malformed.token"
test_api_endpoint "GET Users with Malformed Token" "GET" "/v1/users" 401 "" true
# Test with empty token
+10 -10
View File
@@ -182,13 +182,13 @@ mod tests {
weight: 1.0,
quantity: 10,
};
let _ = GachaRollService::create_gacha_roll(&app_state, roll_dto).await;
let _ = GachaRollService::create_gacha_roll(&app_state, roll_dto).await;
// Create auth header
let mut headers = HeaderMap::new();
headers.insert("authorization", format!("Bearer {}", email).parse().unwrap());
// Create auth header
let mut headers = HeaderMap::new();
headers.insert("Authorization", format!("Bearer {}", email).parse().unwrap());
// Execute roll once
// Execute roll once
let response = GachaRollService::execute_roll_once(headers, &app_state).await;
// Verify response (status + body)
@@ -219,13 +219,13 @@ mod tests {
phone_number: Some("1234567890".to_string()),
role_id: get_role_id(&app_state, "user").await.unwrap(),
};
let _ = UsersService::create_user(&app_state, user_dto).await;
let _ = UsersService::create_user(&app_state, user_dto).await;
// Create auth header
let mut headers = HeaderMap::new();
headers.insert("authorization", format!("Bearer {}", email).parse().unwrap());
// Create auth header
let mut headers = HeaderMap::new();
headers.insert("Authorization", format!("Bearer {}", email).parse().unwrap());
// Execute roll once with no active rolls
// Execute roll once with no active rolls
let response = GachaRollService::execute_roll_once(headers, &app_state).await;
// Verify response (status + body)