feat: Add public routes for hackathons and enhance permissions checks to support both names and IDs

This commit is contained in:
MythEclipse
2025-10-05 20:23:34 +07:00
parent b27e4a4404
commit 7749f6fdec
6 changed files with 74 additions and 10 deletions
+19
View File
@@ -0,0 +1,19 @@
use imphnen_libs::jsonwebtoken::encode_access_token;
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: mk_token <email_or_sub>");
std::process::exit(1);
}
let sub = args[1].clone();
// Use sub as both sub and user_id
match encode_access_token(sub.clone(), sub.clone()) {
Ok(token) => println!("{}", token),
Err(e) => {
eprintln!("Failed to generate token: {:?}", e);
std::process::exit(2);
}
}
}
+2 -1
View File
@@ -13,7 +13,7 @@ use imphnen_cms::{
}; };
use imphnen_dimentorin::dimentorin_router; use imphnen_dimentorin::dimentorin_router;
use imphnen_gacha::gacha_router; use imphnen_gacha::gacha_router;
use imphnen_hackathon::v1::hackathon_protected_routes; use imphnen_hackathon::v1::{hackathon_protected_routes, hackathon_public_routes};
use imphnen_iam::{ use imphnen_iam::{
iam_protected_routes, iam_protected_routes,
iam_public_routes, iam_public_routes,
@@ -41,6 +41,7 @@ pub async fn gateway_service(
let public_routes = Router::new() let public_routes = Router::new()
.merge(iam_public_routes()) .merge(iam_public_routes())
.merge(hackathon_public_routes())
.merge(testimonials_public_routes()) .merge(testimonials_public_routes())
.merge(events_public_routes()); .merge(events_public_routes());
@@ -504,11 +504,9 @@ pub async fn delete_hackathon_submission(
pub fn hackathon_routes() -> Router { pub fn hackathon_routes() -> Router {
Router::new() Router::new()
// Hackathon routes // Hackathon routes
.route("/", post(create_hackathon)) .route("/", post(create_hackathon))
.route("/", get(list_hackathons)) .route("/{id}", put(update_hackathon))
.route("/{id}", get(get_hackathon))
.route("/{id}", put(update_hackathon))
.route("/{id}", delete(delete_hackathon)) .route("/{id}", delete(delete_hackathon))
// Hackathon Events routes // Hackathon Events routes
+10
View File
@@ -8,4 +8,14 @@ pub use hackathon::hackathon_router;
// Main route constructor // Main route constructor
pub fn hackathon_protected_routes() -> Router { pub fn hackathon_protected_routes() -> Router {
Router::new().nest("/hackathons", hackathon_router()) Router::new().nest("/hackathons", hackathon_router())
}
// Public routes for hackathons (only listing and retrieving)
pub fn hackathon_public_routes() -> Router {
use hackathon::hackathon_controller::{list_hackathons, get_hackathon};
Router::new()
.nest("/hackathons", Router::new()
.route("/", axum::routing::get(list_hackathons))
.route("/{id}", axum::routing::get(get_hackathon))
)
} }
@@ -43,8 +43,26 @@ pub async fn permissions_guard(
} }
}; };
// Check permissions from database // Check permissions from database: collect both names and raw ids so checks
let user_permissions: Vec<String> = user.role.permissions.as_ref().unwrap_or(&vec![]).iter().filter_map(|p| p.as_ref().and_then(|pp| pp.name.clone())).collect(); // succeed whether permissions are stored by name or by Thing id.
let user_permissions: Vec<String> = user
.role
.permissions
.as_ref()
.unwrap_or(&vec![])
.iter()
.filter_map(|p| p.as_ref())
.flat_map(|pp| {
let mut res: Vec<String> = Vec::new();
if let Some(name) = pp.name.clone() {
res.push(name);
}
if let Some(id) = pp.id.as_ref().map(|id| id.id.to_raw()) {
res.push(id);
}
res
})
.collect();
// If user has Administrator permission, allow all. // If user has Administrator permission, allow all.
// Accept either the permission name or the canonical permission id. // Accept either the permission name or the canonical permission id.
@@ -88,8 +88,26 @@ where
)); ));
} }
}; };
let user_permissions: Vec<String> = // Collect both permission names and permission ids (raw) so checks work
user.role.permissions.as_ref().unwrap_or(&vec![]).iter().filter_map(|p| p.as_ref().and_then(|pp| pp.name.clone())).collect(); // whether permissions were stored as names or as Thing ids in the role.
let user_permissions: Vec<String> = user
.role
.permissions
.as_ref()
.unwrap_or(&vec![])
.iter()
.filter_map(|p| p.as_ref())
.flat_map(|pp| {
let mut res: Vec<String> = Vec::new();
if let Some(name) = pp.name.clone() {
res.push(name);
}
if let Some(id) = pp.id.as_ref().map(|id| id.id.to_raw()) {
res.push(id);
}
res
})
.collect();
// Check if user has Administrator permission - accept either the permission name or the well-known id // Check if user has Administrator permission - accept either the permission name or the well-known id
let admin_name = PermissionsEnum::Administrator.to_string(); let admin_name = PermissionsEnum::Administrator.to_string();