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_gacha::gacha_router;
use imphnen_hackathon::v1::hackathon_protected_routes;
use imphnen_hackathon::v1::{hackathon_protected_routes, hackathon_public_routes};
use imphnen_iam::{
iam_protected_routes,
iam_public_routes,
@@ -41,6 +41,7 @@ pub async fn gateway_service(
let public_routes = Router::new()
.merge(iam_public_routes())
.merge(hackathon_public_routes())
.merge(testimonials_public_routes())
.merge(events_public_routes());
@@ -504,11 +504,9 @@ pub async fn delete_hackathon_submission(
pub fn hackathon_routes() -> Router {
Router::new()
// Hackathon routes
.route("/", post(create_hackathon))
.route("/", get(list_hackathons))
.route("/{id}", get(get_hackathon))
.route("/{id}", put(update_hackathon))
// Hackathon routes
.route("/", post(create_hackathon))
.route("/{id}", put(update_hackathon))
.route("/{id}", delete(delete_hackathon))
// Hackathon Events routes
+10
View File
@@ -8,4 +8,14 @@ pub use hackathon::hackathon_router;
// Main route constructor
pub fn hackathon_protected_routes() -> 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
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();
// Check permissions from database: collect both names and raw ids so checks
// 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.
// Accept either the permission name or the canonical permission id.
@@ -88,8 +88,26 @@ where
));
}
};
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();
// Collect both permission names and permission ids (raw) so checks work
// 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
let admin_name = PermissionsEnum::Administrator.to_string();