Refactor API endpoints for consistency and clarity
- Updated route paths for hackathon submissions, notifications, registrations, and teams to include more descriptive actions (e.g., "update", "create", "delete"). - Removed deprecated routes and adjusted corresponding test cases to reflect new endpoint structures. - Enhanced test scripts to ensure compatibility with updated API routes and improved error handling for OTP resend functionality. - Adjusted server startup script for better Windows compatibility and streamlined process management.
This commit is contained in:
@@ -35,7 +35,7 @@ use imphnen_iam::v1::teams::teams_repository::TeamsRepository;
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons",
|
||||
path = "/v1/hackathons/create",
|
||||
request_body = HackathonCreateRequestDto,
|
||||
responses(
|
||||
(status = 201, description = "[ADMIN] Hackathon created successfully", body = ResponseSuccessDto<HackathonDto>),
|
||||
@@ -61,7 +61,7 @@ pub async fn create_hackathon(
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/v1/hackathons/{id}",
|
||||
path = "/v1/hackathons/detail/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Hackathon ID")
|
||||
),
|
||||
@@ -115,7 +115,7 @@ pub async fn list_hackathons(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/{id}",
|
||||
path = "/v1/hackathons/update/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Hackathon ID")
|
||||
),
|
||||
@@ -149,7 +149,7 @@ pub async fn update_hackathon(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/{id}",
|
||||
path = "/v1/hackathons/delete/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Hackathon ID")
|
||||
),
|
||||
@@ -236,12 +236,35 @@ pub async fn list_hackathon_events(
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/v1/hackathons/events/detail/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Event ID")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "[PUBLIC] Event retrieved successfully", body = ResponseSuccessDto<HackathonEventDto>),
|
||||
(status = 404, description = "[PUBLIC] Event not found", body = ErrorDto),
|
||||
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
|
||||
),
|
||||
tag = "Hackathon Events"
|
||||
)]
|
||||
pub async fn get_hackathon_event(
|
||||
Extension(state): Extension<AppState>,
|
||||
Path(id): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
match HackathonService::get_hackathon_event(id, &state).await {
|
||||
Ok(response) => (axum::http::StatusCode::OK, Json(response)).into_response(),
|
||||
Err(error) => (StatusCode::from_u16(error.status).unwrap(), Json(error)).into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
put,
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/events/{id}",
|
||||
path = "/v1/hackathons/events/update/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Event ID")
|
||||
),
|
||||
@@ -271,7 +294,7 @@ pub async fn update_hackathon_event(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/events/{id}",
|
||||
path = "/v1/hackathons/events/delete/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Event ID")
|
||||
),
|
||||
@@ -299,7 +322,7 @@ pub async fn delete_hackathon_event(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/{hackathon_id}/timeline",
|
||||
path = "/v1/hackathons/{hackathon_id}/timeline/create",
|
||||
params(
|
||||
("hackathon_id" = String, Path, description = "Hackathon ID")
|
||||
),
|
||||
@@ -354,12 +377,35 @@ pub async fn list_hackathon_timeline(
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/v1/hackathons/timeline/detail/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Timeline ID")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "[PUBLIC] Timeline retrieved successfully", body = ResponseSuccessDto<HackathonTimelineDto>),
|
||||
(status = 404, description = "[PUBLIC] Timeline not found", body = ErrorDto),
|
||||
(status = 500, description = "[PUBLIC] Internal server error", body = ErrorDto)
|
||||
),
|
||||
tag = "Hackathon Timeline"
|
||||
)]
|
||||
pub async fn get_hackathon_timeline(
|
||||
Extension(state): Extension<AppState>,
|
||||
Path(id): Path<String>,
|
||||
) -> impl IntoResponse {
|
||||
match HackathonService::get_hackathon_timeline(id, &state).await {
|
||||
Ok(response) => (axum::http::StatusCode::OK, Json(response)).into_response(),
|
||||
Err(error) => (StatusCode::from_u16(error.status).unwrap(), Json(error)).into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
put,
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/timeline/{id}",
|
||||
path = "/v1/hackathons/timeline/update/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Timeline ID")
|
||||
),
|
||||
@@ -389,7 +435,7 @@ pub async fn update_hackathon_timeline(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/timeline/{id}",
|
||||
path = "/v1/hackathons/timeline/delete/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Timeline ID")
|
||||
),
|
||||
@@ -417,7 +463,7 @@ pub async fn delete_hackathon_timeline(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/{hackathon_id}/teams/{team_id}/submissions",
|
||||
path = "/v1/hackathons/{hackathon_id}/teams/{team_id}/submissions/create",
|
||||
params(
|
||||
("hackathon_id" = String, Path, description = "Hackathon ID"),
|
||||
("team_id" = String, Path, description = "Team ID")
|
||||
@@ -524,7 +570,7 @@ pub async fn list_hackathon_submissions(
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/v1/hackathons/submissions/{id}",
|
||||
path = "/v1/hackathons/submissions/detail/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Submission ID")
|
||||
),
|
||||
@@ -550,7 +596,7 @@ pub async fn get_hackathon_submission(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/submissions/{id}",
|
||||
path = "/v1/hackathons/submissions/update/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Submission ID")
|
||||
),
|
||||
@@ -610,7 +656,7 @@ pub async fn submit_hackathon_submission(
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/submissions/{id}",
|
||||
path = "/v1/hackathons/submissions/delete/{id}",
|
||||
params(
|
||||
("id" = String, Path, description = "Submission ID")
|
||||
),
|
||||
@@ -687,7 +733,7 @@ pub struct UpdateStatusPayload {
|
||||
security(
|
||||
("Bearer" = [])
|
||||
),
|
||||
path = "/v1/hackathons/submissions/{id}/status",
|
||||
path = "/v1/hackathons/submissions/update/{id}/status",
|
||||
params(
|
||||
("id" = String, Path, description = "Submission ID")
|
||||
),
|
||||
@@ -1201,42 +1247,42 @@ pub async fn change_hackathon_status(
|
||||
pub fn hackathon_routes() -> Router {
|
||||
Router::new()
|
||||
// Hackathon routes
|
||||
.route("/", post(create_hackathon))
|
||||
.route("/complete", post(create_hackathon_complete))
|
||||
.route("/{id}", put(update_hackathon))
|
||||
.route("/create", post(create_hackathon))
|
||||
.route("/create-complete", post(create_hackathon_complete))
|
||||
.route("/detail/{id}", get(get_hackathon))
|
||||
.route("/update/{id}", put(update_hackathon))
|
||||
.route("/delete/{id}", delete(delete_hackathon))
|
||||
.route("/{id}/status", patch(change_hackathon_status))
|
||||
.route("/{id}", delete(delete_hackathon))
|
||||
|
||||
// Hackathon Events routes
|
||||
.route("/{hackathon_id}/events", post(create_hackathon_event))
|
||||
.route("/{hackathon_id}/events/create", post(create_hackathon_event))
|
||||
.route("/{hackathon_id}/events", get(list_hackathon_events))
|
||||
.route("/events/{id}", put(update_hackathon_event))
|
||||
.route("/events/{id}", delete(delete_hackathon_event))
|
||||
.route("/events/detail/{id}", get(get_hackathon_event))
|
||||
.route("/events/update/{id}", put(update_hackathon_event))
|
||||
.route("/events/delete/{id}", delete(delete_hackathon_event))
|
||||
|
||||
// Hackathon Timeline routes
|
||||
.route("/{hackathon_id}/timeline", post(create_hackathon_timeline))
|
||||
.route("/{hackathon_id}/timeline/create", post(create_hackathon_timeline))
|
||||
.route("/{hackathon_id}/timeline", get(list_hackathon_timeline))
|
||||
.route("/timeline/{id}", put(update_hackathon_timeline))
|
||||
.route("/timeline/{id}", delete(delete_hackathon_timeline))
|
||||
.route("/timeline/detail/{id}", get(get_hackathon_timeline))
|
||||
.route("/timeline/update/{id}", put(update_hackathon_timeline))
|
||||
.route("/timeline/delete/{id}", delete(delete_hackathon_timeline))
|
||||
|
||||
// Hackathon Submissions routes
|
||||
.route("/{hackathon_id}/teams/{team_id}/submissions", post(create_hackathon_submission))
|
||||
.route("/{hackathon_id}/teams/{team_id}/submissions/create", post(create_hackathon_submission))
|
||||
.route("/{hackathon_id}/submissions", get(list_hackathon_submissions))
|
||||
.route("/submissions/{id}", get(get_hackathon_submission))
|
||||
.route("/submissions/{id}", put(update_hackathon_submission))
|
||||
.route("/submissions/detail/{id}", get(get_hackathon_submission))
|
||||
.route("/submissions/update/{id}", put(update_hackathon_submission))
|
||||
.route("/submissions/delete/{id}", delete(delete_hackathon_submission))
|
||||
.route("/submissions/{id}/submit", post(submit_hackathon_submission))
|
||||
.route("/submissions/{id}", delete(delete_hackathon_submission))
|
||||
|
||||
// Admin-only submission status endpoint
|
||||
.route("/submissions/{id}/status", put(update_submission_status))
|
||||
.route("/submissions/update/{id}/status", put(update_submission_status))
|
||||
|
||||
// Admin sensitive data endpoint
|
||||
.route("/{hackathon_id}/admin/sensitive-data", post(post_admin_manage_sensitive_data))
|
||||
// alias route used by the integration tests
|
||||
.route("/{hackathon_id}/admin/manage", post(post_admin_manage_sensitive_data))
|
||||
|
||||
// Participants routes
|
||||
.route("/{id}/participants", post(register_participant))
|
||||
.route("/{id}/participants/create", post(register_participant))
|
||||
.route("/{id}/participants", get(list_participants))
|
||||
}
|
||||
|
||||
|
||||
@@ -332,6 +332,23 @@ impl<'a> HackathonRepository<'a> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[instrument(skip(self, id), err)]
|
||||
pub async fn get_hackathon_event_by_id(&self, id: String) -> Result<HackathonEventsSchema> {
|
||||
let table = ResourceEnum::HackathonEvents.to_string();
|
||||
|
||||
let existing: Option<HackathonEventsSchema> = self.state.surrealdb_ws
|
||||
.select((table, id.clone()))
|
||||
.await?;
|
||||
|
||||
let event = existing.ok_or_else(|| anyhow!("Event not found"))?;
|
||||
|
||||
if event.is_deleted {
|
||||
bail!("Event not found");
|
||||
}
|
||||
|
||||
Ok(event)
|
||||
}
|
||||
|
||||
#[instrument(skip(self, id, updates), err)]
|
||||
pub async fn update_hackathon_event(&self, id: String, updates: HackathonEventUpdateRequestDto) -> Result<HackathonEventsSchema> {
|
||||
let table = ResourceEnum::HackathonEvents.to_string();
|
||||
@@ -465,6 +482,23 @@ impl<'a> HackathonRepository<'a> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
#[instrument(skip(self, id), err)]
|
||||
pub async fn get_hackathon_timeline_by_id(&self, id: String) -> Result<HackathonTimelineSchema> {
|
||||
let table = ResourceEnum::HackathonTimeline.to_string();
|
||||
|
||||
let existing: Option<HackathonTimelineSchema> = self.state.surrealdb_ws
|
||||
.select((table, id.clone()))
|
||||
.await?;
|
||||
|
||||
let timeline = existing.ok_or_else(|| anyhow!("Timeline not found"))?;
|
||||
|
||||
if timeline.is_deleted {
|
||||
bail!("Timeline not found");
|
||||
}
|
||||
|
||||
Ok(timeline)
|
||||
}
|
||||
|
||||
#[instrument(skip(self, id, updates), err)]
|
||||
pub async fn update_hackathon_timeline(&self, id: String, updates: HackathonTimelineUpdateRequestDto) -> Result<HackathonTimelineSchema> {
|
||||
let table = ResourceEnum::HackathonTimeline.to_string();
|
||||
|
||||
@@ -58,6 +58,10 @@ pub trait HackathonServiceTrait: Send + Sync + 'static {
|
||||
payload: HackathonEventCreateRequestDto,
|
||||
state: &AppState,
|
||||
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>>;
|
||||
fn get_hackathon_event(
|
||||
id: String,
|
||||
state: &AppState,
|
||||
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>>;
|
||||
fn list_hackathon_events(
|
||||
meta: MetaRequestDto,
|
||||
hackathon_id: String,
|
||||
@@ -79,6 +83,10 @@ pub trait HackathonServiceTrait: Send + Sync + 'static {
|
||||
payload: HackathonTimelineCreateRequestDto,
|
||||
state: &AppState,
|
||||
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>>;
|
||||
fn get_hackathon_timeline(
|
||||
id: String,
|
||||
state: &AppState,
|
||||
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>>;
|
||||
fn list_hackathon_timeline(
|
||||
meta: MetaRequestDto,
|
||||
hackathon_id: String,
|
||||
@@ -503,6 +511,40 @@ impl HackathonServiceTrait for HackathonService {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_hackathon_event(
|
||||
id: String,
|
||||
state: &AppState,
|
||||
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>> {
|
||||
let state = state.to_owned();
|
||||
Box::pin(async move {
|
||||
let repo = HackathonRepository::new(&state);
|
||||
|
||||
match repo.get_hackathon_event_by_id(id).await {
|
||||
Ok(event) => {
|
||||
let dto = HackathonEventDto::from(event);
|
||||
Ok(ResponseSuccessDto { data: dto })
|
||||
}
|
||||
Err(e) => {
|
||||
let error_msg = e.to_string();
|
||||
if error_msg.contains("not found") {
|
||||
Err(ErrorDto {
|
||||
status: StatusCode::NOT_FOUND.as_u16(),
|
||||
message: "Event not found".to_string(),
|
||||
details: None,
|
||||
})
|
||||
} else {
|
||||
error!("Failed to get event: {}", e);
|
||||
Err(ErrorDto {
|
||||
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
|
||||
message: "Failed to get event".to_string(),
|
||||
details: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn list_hackathon_events(
|
||||
meta: MetaRequestDto,
|
||||
hackathon_id: String,
|
||||
@@ -662,6 +704,40 @@ impl HackathonServiceTrait for HackathonService {
|
||||
})
|
||||
}
|
||||
|
||||
fn get_hackathon_timeline(
|
||||
id: String,
|
||||
state: &AppState,
|
||||
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>> {
|
||||
let state = state.to_owned();
|
||||
Box::pin(async move {
|
||||
let repo = HackathonRepository::new(&state);
|
||||
|
||||
match repo.get_hackathon_timeline_by_id(id).await {
|
||||
Ok(timeline) => {
|
||||
let dto = HackathonTimelineDto::from(timeline);
|
||||
Ok(ResponseSuccessDto { data: dto })
|
||||
}
|
||||
Err(e) => {
|
||||
let error_msg = e.to_string();
|
||||
if error_msg.contains("not found") {
|
||||
Err(ErrorDto {
|
||||
status: StatusCode::NOT_FOUND.as_u16(),
|
||||
message: "Timeline not found".to_string(),
|
||||
details: None,
|
||||
})
|
||||
} else {
|
||||
error!("Failed to get timeline: {}", e);
|
||||
Err(ErrorDto {
|
||||
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
|
||||
message: "Failed to get timeline".to_string(),
|
||||
details: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn list_hackathon_timeline(
|
||||
meta: MetaRequestDto,
|
||||
hackathon_id: String,
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn hackathon_protected_routes() -> Router {
|
||||
use hackathon::hackathon_controller::{update_submission_status, get_admin_hackathon_results};
|
||||
Router::new()
|
||||
.nest("/hackathons", hackathon_router())
|
||||
.route("/hackathons/submissions/{id}/status", axum::routing::patch(update_submission_status))
|
||||
.route("/hackathons/submissions/update/{id}/status", axum::routing::patch(update_submission_status))
|
||||
.route("/hackathons/{hackathon_id}/admin/results", axum::routing::get(get_admin_hackathon_results))
|
||||
.merge(registrations_router())
|
||||
.merge(notifications_router())
|
||||
@@ -26,7 +26,6 @@ pub fn hackathon_protected_routes() -> Router {
|
||||
pub fn hackathon_public_routes() -> Router {
|
||||
use hackathon::hackathon_controller::{
|
||||
list_hackathons,
|
||||
get_hackathon,
|
||||
search_hackathons,
|
||||
get_user_hackathon_submissions,
|
||||
get_public_hackathon_results,
|
||||
@@ -35,7 +34,6 @@ pub fn hackathon_public_routes() -> Router {
|
||||
Router::new()
|
||||
.nest("/hackathons", Router::new()
|
||||
.route("/", axum::routing::get(list_hackathons))
|
||||
.route("/{id}", axum::routing::get(get_hackathon))
|
||||
.route("/{id}/results", axum::routing::get(get_public_hackathon_results))
|
||||
.route("/search", axum::routing::post(search_hackathons))
|
||||
)
|
||||
|
||||
@@ -48,14 +48,13 @@ pub async fn get_notifications_handler(
|
||||
/// Mark a notification as read
|
||||
#[utoipa::path(
|
||||
put,
|
||||
path = "/v1/notifications/{id}/read",
|
||||
path = "/v1/notifications/update/{id}/read",
|
||||
tags = ["notifications"],
|
||||
params(
|
||||
("id" = String, Path, description = "Notification ID"),
|
||||
("id" = String, Path, description = "Notification ID")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Successfully marked notification as read", body = MarkAsReadResponseDto),
|
||||
(status = 400, description = "Notification already marked as read"),
|
||||
(status = 200, description = "Successfully marked as read", body = MarkAsReadResponseDto),
|
||||
(status = 401, description = "Unauthorized - Invalid or missing token"),
|
||||
(status = 403, description = "Forbidden - Not the notification owner"),
|
||||
(status = 404, description = "Notification not found"),
|
||||
@@ -107,7 +106,7 @@ pub async fn mark_all_as_read_handler(
|
||||
/// Delete a notification
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
path = "/v1/notifications/{id}",
|
||||
path = "/v1/notifications/delete/{id}",
|
||||
tags = ["notifications"],
|
||||
params(
|
||||
("id" = String, Path, description = "Notification ID"),
|
||||
@@ -165,8 +164,8 @@ pub async fn get_unread_count_handler(
|
||||
pub fn notifications_router() -> Router {
|
||||
Router::new()
|
||||
.route("/notifications", get(get_notifications_handler))
|
||||
.route("/notifications/{id}/read", put(mark_as_read_handler))
|
||||
.route("/notifications/update/{id}/read", put(mark_as_read_handler))
|
||||
.route("/notifications/read-all", put(mark_all_as_read_handler))
|
||||
.route("/notifications/{id}", delete(delete_notification_handler))
|
||||
.route("/notifications/delete/{id}", delete(delete_notification_handler))
|
||||
.route("/notifications/unread/count", get(get_unread_count_handler))
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ use super::{
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// POST /v1/hackathons/{id}/register
|
||||
// POST /v1/hackathons/{id}/registrations/create
|
||||
// ============================================
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/v1/hackathons/{id}/register",
|
||||
path = "/v1/hackathons/{id}/registrations/create",
|
||||
tag = "registrations",
|
||||
summary = "Register for a hackathon",
|
||||
description = "Submit a registration for a hackathon. User must be authenticated.",
|
||||
@@ -137,14 +137,14 @@ pub async fn get_my_hackathons(
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// PUT /v1/hackathons/{hackathon_id}/registrations/{registration_id}/status
|
||||
// PUT /v1/hackathons/{hackathon_id}/registrations/update/{registration_id}/status
|
||||
// ============================================
|
||||
#[utoipa::path(
|
||||
put,
|
||||
path = "/v1/hackathons/{hackathon_id}/registrations/{registration_id}/status",
|
||||
path = "/v1/hackathons/{hackathon_id}/registrations/update/{registration_id}/status",
|
||||
tag = "registrations",
|
||||
summary = "Update registration status",
|
||||
description = "Approve, reject, or update the status of a registration. Requires admin/organizer permissions.",
|
||||
description = "Update the status of a hackathon registration (admin/organizer only).",
|
||||
params(
|
||||
("hackathon_id" = String, Path, description = "Hackathon ID"),
|
||||
("registration_id" = String, Path, description = "Registration ID")
|
||||
@@ -268,7 +268,7 @@ pub async fn get_registration_stats(
|
||||
pub fn registrations_router() -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
"/hackathons/{id}/register",
|
||||
"/hackathons/{id}/registrations/create",
|
||||
post(post_register_hackathon),
|
||||
)
|
||||
.route(
|
||||
@@ -280,7 +280,7 @@ pub fn registrations_router() -> Router {
|
||||
get(get_registration_stats),
|
||||
)
|
||||
.route(
|
||||
"/hackathons/{hackathon_id}/registrations/{registration_id}/status",
|
||||
"/hackathons/{hackathon_id}/registrations/update/{registration_id}/status",
|
||||
put(put_update_registration_status),
|
||||
)
|
||||
.route(
|
||||
|
||||
Reference in New Issue
Block a user