From ffe6d464d72485ad807aad81c9745f1112717124 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sun, 9 May 2021 16:17:58 +0200 Subject: [PATCH] Add support for admin routes --- config.yaml | 3 ++ .../admin/admin_account_controller.rs | 12 +++++++ src/controllers/admin/mod.rs | 5 +++ src/controllers/mod.rs | 2 ++ src/data/config.rs | 3 ++ src/data/http_request_handler.rs | 11 ++++++ src/routes.rs | 36 +++++++++++++++++++ src/server.rs | 33 +++++++++++++---- 8 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 src/controllers/admin/admin_account_controller.rs create mode 100644 src/controllers/admin/mod.rs diff --git a/config.yaml b/config.yaml index 8827746..edbff4d 100644 --- a/config.yaml +++ b/config.yaml @@ -70,6 +70,9 @@ rtc-relay: allow-video: true max-users-per-video-calls: 6 +# Admin URL +admin-url: https://console.communiquons.org + # List of #Forez groups # # This option allows to enable some extra features for these groups diff --git a/src/controllers/admin/admin_account_controller.rs b/src/controllers/admin/admin_account_controller.rs new file mode 100644 index 0000000..8b0f94c --- /dev/null +++ b/src/controllers/admin/admin_account_controller.rs @@ -0,0 +1,12 @@ +//! # Admin account controller +//! +//! @author Pierre Hubert + +use crate::data::http_request_handler::HttpRequestHandler; +use crate::routes::RequestResult; +use crate::data::base_request_handler::BaseRequestHandler; + +/// Get admin auth options +pub fn get_auth_options(r: &mut HttpRequestHandler) -> RequestResult { + r.ok() +} \ No newline at end of file diff --git a/src/controllers/admin/mod.rs b/src/controllers/admin/mod.rs new file mode 100644 index 0000000..3cc1dc5 --- /dev/null +++ b/src/controllers/admin/mod.rs @@ -0,0 +1,5 @@ +//! # Admin controllers +//! +//! @author Pierre Hubert + +pub mod admin_account_controller; \ No newline at end of file diff --git a/src/controllers/mod.rs b/src/controllers/mod.rs index 4d4192f..b2fc627 100644 --- a/src/controllers/mod.rs +++ b/src/controllers/mod.rs @@ -1,3 +1,5 @@ +pub mod admin; + pub mod server_controller; pub mod user_ws_controller; pub mod rtc_relay_controller; diff --git a/src/data/config.rs b/src/data/config.rs index eeb67f2..9f295a2 100644 --- a/src/data/config.rs +++ b/src/data/config.rs @@ -51,6 +51,7 @@ pub struct Config { pub independent_push_service: Option, pub database: DatabaseConfig, pub rtc_relay: Option, + pub admin_url: String, pub forez_groups: Vec, } @@ -152,6 +153,8 @@ impl Config { rtc_relay: rtc_config, + admin_url: Self::yaml_str(parsed, "admin-url"), + forez_groups: parsed["forez_groups"] .as_vec() .unwrap_or(&vec![]) diff --git a/src/data/http_request_handler.rs b/src/data/http_request_handler.rs index bdf11d2..fc1faa4 100644 --- a/src/data/http_request_handler.rs +++ b/src/data/http_request_handler.rs @@ -129,6 +129,17 @@ impl HttpRequestHandler { } } } + + /// Check admin origin + pub fn check_admin_origin(&mut self) -> Res { + if let Some(header) = self.request.headers().get("Origin") { + if header.to_str()?.eq(&conf().admin_url) { + return Ok(()); + } + } + + self.bad_request("Invalid origin for admin requests!".to_string()) + } } impl BaseRequestHandler for HttpRequestHandler { diff --git a/src/routes.rs b/src/routes.rs index 78d505b..cd57c92 100644 --- a/src/routes.rs +++ b/src/routes.rs @@ -1,6 +1,7 @@ use std::error::Error; use crate::controllers::{account_controller, comments_controller, conversations_controller, forez_controller, friends_controller, groups_controller, likes_controller, notifications_controller, posts_controller, push_notifications_controller, search_controller, server_controller, settings_controller, surveys_controller, user_controller, user_ws_controller, virtual_directory_controller, web_app_controller}; +use crate::controllers::admin::*; use crate::data::http_request_handler::HttpRequestHandler; use crate::routes::Method::{GET, POST}; @@ -34,6 +35,15 @@ pub enum LimitPolicy { ANY(u64), } +/// Scope of the route +pub enum RouteScope { + // Route accessible by a "normal" user of Comunic + USER, + + // Route accessible by an administrator of Comunic + ADMIN, +} + impl LimitPolicy { pub fn is_none(&self) -> bool { matches!(self, LimitPolicy::NONE) @@ -54,6 +64,9 @@ pub type RequestResult = Result<(), Box>; pub type RequestProcess = Box RequestResult>; pub struct Route { + /// Route scope + pub scope: RouteScope, + /// The Verb used for the request pub method: Method, @@ -73,6 +86,7 @@ pub struct Route { impl Route { pub fn get_without_login(uri: &'static str, func: RequestProcess) -> Route { Route { + scope: RouteScope::USER, method: GET, need_login: false, uri, @@ -83,6 +97,7 @@ impl Route { pub fn post_without_login(uri: &'static str, func: RequestProcess) -> Route { Route { + scope: RouteScope::USER, method: POST, need_login: false, uri, @@ -93,6 +108,7 @@ impl Route { pub fn limited_post_without_login(uri: &'static str, func: RequestProcess, limit_policy: LimitPolicy) -> Route { Route { + scope: RouteScope::USER, method: POST, need_login: false, uri, @@ -103,6 +119,7 @@ impl Route { pub fn post(uri: &'static str, func: RequestProcess) -> Route { Route { + scope: RouteScope::USER, method: POST, need_login: true, uri, @@ -113,6 +130,7 @@ impl Route { pub fn limited_post(uri: &'static str, func: RequestProcess, limit_policy: LimitPolicy) -> Route { Route { + scope: RouteScope::USER, method: POST, need_login: true, uri, @@ -120,6 +138,17 @@ impl Route { limit_policy, } } + + pub fn limited_admin_post_without_login(uri: &'static str, func: RequestProcess, limit_policy: LimitPolicy) -> Route { + Route { + scope: RouteScope::ADMIN, + method: POST, + need_login: false, + uri, + func, + limit_policy, + } + } } /// Get the list of routes available @@ -301,5 +330,12 @@ pub fn get_routes() -> Vec { // Forez controller Route::post("/forez/get_groups", Box::new(forez_controller::get_list_groups)), Route::post("/forez/get_member_info", Box::new(forez_controller::get_member_info)), + + + // === ADMIN ROUTES === + + + // Admin accounts controller + Route::limited_admin_post_without_login("/admin/accounts/auth_options", Box::new(admin_account_controller::get_auth_options), LimitPolicy::FAILURE(5)), ] } \ No newline at end of file diff --git a/src/server.rs b/src/server.rs index 20dc72e..33553ef 100644 --- a/src/server.rs +++ b/src/server.rs @@ -18,7 +18,7 @@ use crate::data::base_request_handler::{BaseRequestHandler, PostFile, RequestVal use crate::data::config::Config; use crate::data::http_request_handler::HttpRequestHandler; use crate::helpers::{api_helper, requests_limit_helper}; -use crate::routes::{get_routes, RequestResult, Route}; +use crate::routes::{get_routes, RequestResult, Route, RouteScope}; use crate::routes::Method::{GET, POST}; use crate::utils::user_data_utils::user_data_path; @@ -209,14 +209,33 @@ fn process_simple_route(route: &Route, req: &mut HttpRequestHandler) -> RequestR req.too_many_requests("Too many request. Please try again later.")?; } - // Validate client token - req.check_client_token()?; + // Check if the user is allowed to access the route + match route.scope { - // Check user token, if required - if route.need_login || req.has_post_parameter("userToken1") { - req.check_user_token()?; + // "Normal" user route + RouteScope::USER => { + // Validate client token + req.check_client_token()?; + + // Check user token, if required + if route.need_login || req.has_post_parameter("token") { + req.check_user_token()?; + } + }, + + // "Admin" user scope + RouteScope::ADMIN => { + req.check_admin_origin()?; + + if route.need_login { + // TODO : implement + unimplemented!(); + } + } } + + let res: RequestResult = (route.func)(req); requests_limit_helper::trigger_after(res.is_ok(), req, route)?; @@ -250,7 +269,7 @@ async fn process_request(custom_req: CustomRequest) -> HttpResponse { // Check if a route was found if let None = route { - return HttpResponse::NotFound().json(HttpError::not_found("Method not found!")); + return HttpResponse::NotFound().json(HttpError::not_found("Route not found!")); } let route = route.unwrap();