diff --git a/service/Cargo.toml b/service/Cargo.toml index 474b911..bc51c7f 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -13,7 +13,6 @@ path = "src/lib.rs" [dependencies] actix-web = "4.4.0" -actix-rt = "2.9.0" actix-cors = "0.6.4" actix-web-httpauth = "0.8.1" chrono = { version = "0.4.31", features = ["serde"] } diff --git a/service/src/auth/model.rs b/service/src/auth/model.rs index 9041f69..b8170ac 100644 --- a/service/src/auth/model.rs +++ b/service/src/auth/model.rs @@ -170,3 +170,14 @@ impl FromRequest for JwtAuth { } } } + +pub fn verify_role(auth: &JwtAuth, role: &str) -> Result<(), ServiceError> { + if auth.user.role == role { + Ok(()) + } else { + Err(ServiceError { + status: 403, + message: "Forbidden".to_string() + }) + } +} diff --git a/service/src/bot/api/routes.rs b/service/src/bot/api/routes.rs index 8159446..d1e2576 100644 --- a/service/src/bot/api/routes.rs +++ b/service/src/bot/api/routes.rs @@ -1,15 +1,19 @@ use std::{sync::Arc, pin::Pin}; -use actix_web::{get, post, put, delete, web, HttpResponse, HttpRequest, ResponseError}; +use actix_web::{get, post, web, HttpResponse, ResponseError}; use log::warn; use serde::{Serialize, Deserialize}; use serenity::model::prelude::{GuildChannel, ChannelType}; use siren::ServiceError; -use crate::{AppState, bot::commands::audio::{play::play_track, join}, db::guilds::{InsertGuild, QueryGuild}, auth::JwtAuth}; +use crate::{AppState, bot::commands::audio::{play::play_track, join}, db::guilds::QueryGuild, auth::{JwtAuth, verify_role}}; #[get("/guilds")] async fn get_guilds(data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_results = &data.http.get_guilds(None, None).await; let guilds = match guild_results { Ok(guilds) => guilds, @@ -23,6 +27,10 @@ async fn get_guilds(data: web::Data>, auth: JwtAuth) -> HttpRespon #[get("/{id}/text")] async fn get_text_channels(id: web::Path, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let channel_results = &data.http.get_channels(id.parse::().unwrap()).await; let channels = match channel_results { Ok(channels) => channels.iter().filter(|c| c.kind == ChannelType::Text).collect::>(), @@ -36,6 +44,10 @@ async fn get_text_channels(id: web::Path, data: web::Data> #[get("/{id}/voice")] async fn get_voice_channels(id: web::Path, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let channel_results = &data.http.get_channels(id.parse::().unwrap()).await; let channels = match channel_results { Ok(channels) => channels.iter().filter(|c| c.kind == ChannelType::Voice).collect::>(), @@ -54,6 +66,10 @@ struct ChannelMessage { #[post("/{guild_id}/text/{channel_id}/message")] async fn send_message(path: web::Path<(String, String)>, text: web::Json, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let (guild_id, channel_id) = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -116,6 +132,10 @@ struct PlayRequest { #[post("/{guild_id}/voice/{channel_id}/play")] async fn play(path: web::Path<(String, String)>, play_request: web::Json, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let (guild_id, channel_id) = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -168,6 +188,10 @@ async fn play(path: web::Path<(String, String)>, play_request: web::Json, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_id = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -190,6 +214,10 @@ async fn stop(path: web::Path, data: web::Data>, auth: Jwt #[post("/{guild_id}/voice/resume")] async fn resume(path: web::Path, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_id = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -218,6 +246,10 @@ async fn resume(path: web::Path, data: web::Data>, auth: J #[post("/{guild_id}/voice/pause")] async fn pause(path: web::Path, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_id = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -251,6 +283,10 @@ struct SetVolume { #[get("/{guild_id}/voice/volume")] async fn get_volume(path: web::Path, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_id = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -279,6 +315,10 @@ async fn get_volume(path: web::Path, auth: JwtAuth) -> HttpResponse { #[post("/{guild_id}/voice/volume")] async fn set_volume(path: web::Path, volume: web::Json::, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_id = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, @@ -308,6 +348,10 @@ async fn set_volume(path: web::Path, volume: web::Json::, dat #[post("/{guild_id}/voice/skip")] async fn skip(path: web::Path, data: web::Data>, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let guild_id = path.into_inner(); let guild_id = match guild_id.parse::() { Ok(id) => id, diff --git a/service/src/db/messages/routes.rs b/service/src/db/messages/routes.rs index cb58f36..507a361 100644 --- a/service/src/db/messages/routes.rs +++ b/service/src/db/messages/routes.rs @@ -3,7 +3,7 @@ use log::error; use serde::{Serialize, Deserialize}; use siren::{GetResponse, Metadata, ServiceError}; -use crate::{db::messages::{QueryMessage, QueryFilters, InsertMessage}, auth::JwtAuth}; +use crate::{db::messages::{QueryMessage, QueryFilters, InsertMessage}, auth::{JwtAuth, verify_role}}; #[derive(Serialize, Deserialize)] struct GetAllParams { @@ -22,6 +22,10 @@ struct GetAllParams { #[get("/messages")] async fn get_all(req: HttpRequest, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let params = match web::Query::::from_query(req.query_string()) { Ok(params) => params, Err(err) => return ResponseError::error_response(&ServiceError { @@ -65,6 +69,10 @@ async fn get_all(req: HttpRequest, auth: JwtAuth) -> HttpResponse { #[post("/messages")] async fn create(message: web::Json, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; match InsertMessage::insert(message.into_inner()) { Ok(message) => HttpResponse::Created().json(message), Err(err) => { diff --git a/service/src/db/spells/routes.rs b/service/src/db/spells/routes.rs index 501a6bf..4b95e90 100644 --- a/service/src/db/spells/routes.rs +++ b/service/src/db/spells/routes.rs @@ -3,7 +3,7 @@ use log::error; use serde::{Serialize, Deserialize}; use siren::{GetResponse, Metadata, ServiceError}; -use crate::{db::spells::{QuerySpell, QueryFilters}, auth::JwtAuth}; +use crate::{db::spells::{QuerySpell, QueryFilters}, auth::{JwtAuth, verify_role}}; use super::{Spell, InsertSpell}; @@ -135,6 +135,10 @@ async fn get_by_id(id: web::Path) -> HttpResponse { #[post("/spells")] async fn create(spell: web::Json, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; match InsertSpell::insert(spell.into_inner().into()) { Ok(spell) => HttpResponse::Created().json(Spell::from(spell)), Err(err) => { @@ -146,6 +150,10 @@ async fn create(spell: web::Json, auth: JwtAuth) -> HttpResponse { #[put("/spells/{id}")] async fn update(id: web::Path, spell: web::Json, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let id = match id.parse::() { Ok(id) => id, Err(err) => return ResponseError::error_response(&ServiceError { @@ -164,6 +172,10 @@ async fn update(id: web::Path, spell: web::Json, auth: JwtAuth) - #[delete("/spells/{id}")] async fn delete(id: web::Path, auth: JwtAuth) -> HttpResponse { + let _ = match verify_role(&auth, "admin") { + Ok(_) => {}, + Err(err) => return ResponseError::error_response(&err) + }; let id = match id.parse::() { Ok(id) => id, Err(err) => return ResponseError::error_response(&ServiceError { diff --git a/service/src/main.rs b/service/src/main.rs index 2aa1c45..4322e3f 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -112,21 +112,6 @@ async fn main() -> std::io::Result<()> { let port = env::var("SERVICE_PORT").unwrap_or("5000".to_string()); let server = match HttpServer::new(move || { - // let private_key = actix_web::cookie::Key::generate(); - // let redis_host = env::var("REDIS_HOST").unwrap_or("localhost".to_string()); - // let redis_port = env::var("REDIS_PORT").unwrap_or("6379".to_string()); - // let session = SessionMiddleware::builder( - // RedisActorSessionStore::new(format!("{}:{}", redis_host, redis_port)), - // CookieSessionStore::default(), - // private_key - // ) - // .session_lifecycle(BrowserSession::default()) - // .cookie_name("auth".to_owned()) - // .cookie_secure(false) - // .cookie_http_only(false) - // .cookie_domain(Some("localhost".to_owned())) - // .cookie_path("/".to_owned()) - // .build(); let cors = Cors::default() .allow_any_origin() .allow_any_method() @@ -134,8 +119,6 @@ async fn main() -> std::io::Result<()> { .supports_credentials() .max_age(3600); App::new() - // .wrap(IdentityMiddleware::default()) - // .wrap(session) .wrap(cors) .app_data(web::Data::new(Arc::clone(&app_data))) .configure(crate::db::messages::init_routes)