From bedfe75355ddab5d3c0e70c73159b89b101c7d25 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 20 May 2021 02:35:34 -0400 Subject: [PATCH] enable-alpha cookie endpoint --- .env | 3 ++ src/endpoints/misc/enable_alpha.rs | 53 ++++++++++++++++++++++++++++++ src/endpoints/misc/mod.rs | 1 + src/endpoints/mod.rs | 1 + src/endpoints/root_index.rs | 4 +-- src/main.rs | 10 +++++- src/server_state.rs | 3 ++ 7 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/endpoints/misc/enable_alpha.rs create mode 100644 src/endpoints/misc/mod.rs diff --git a/.env b/.env index 9793767d64..17a2fc83df 100644 --- a/.env +++ b/.env @@ -4,3 +4,6 @@ DATABASE_URL=mysql://root:root@localhost/storyteller # This setting turns that on and requires a `sql-data.json` cache file instead. # See https://github.com/launchbadge/sqlx/tree/master/sqlx-cli#readme SQLX_OFFLINE=true + +# We can't serve HTTPS locally without self-signed certificate nonsense. +COOKIE_SECURE=false diff --git a/src/endpoints/misc/enable_alpha.rs b/src/endpoints/misc/enable_alpha.rs new file mode 100644 index 0000000000..7b5c11cb97 --- /dev/null +++ b/src/endpoints/misc/enable_alpha.rs @@ -0,0 +1,53 @@ +use actix_http::http::StatusCode; +use actix_web::{HttpResponse, HttpRequest, Responder, get, web, HttpMessage}; +use log::info; +use actix_http::cookie::Cookie; +use crate::server_state::ServerState; +use std::sync::Arc; +use actix_web::web::Query; + +const ALPHA_COOKIE_NAME : &'static str = "enable-alpha"; +const CONTENT_TYPE : &'static str = "text/html; charset=utf-8"; + +#[derive(Deserialize)] +struct QueryFields { + enable: Option, +} + +#[get("/alpha")] +pub async fn enable_alpha(http_request: HttpRequest, + query: Query, + server_state: web::Data>) -> impl Responder +{ + info!("GET /alpha"); + + let cookie = Cookie::build(ALPHA_COOKIE_NAME, "true") + .domain(&server_state.env_config.cookie_domain) + .secure(server_state.env_config.cookie_secure) // HTTPS-only + .http_only(false) // This is meant to be exposed to Javascript! + .permanent() + .finish(); + + match query.enable { + None => { + let cookie_exists = http_request.cookie(ALPHA_COOKIE_NAME).is_some(); + + HttpResponse::build(StatusCode::OK) + .content_type(CONTENT_TYPE) + .body(format!("

use ?enable={{true, false}}; current `{}` cookie state = {}

", + ALPHA_COOKIE_NAME, cookie_exists)) + } + Some(true) => { + HttpResponse::build(StatusCode::OK) + .content_type(CONTENT_TYPE) + .cookie(cookie) + .body(format!("

?enable=true; setting `{}` cookie

", ALPHA_COOKIE_NAME)) + } + Some(false) => { + HttpResponse::build(StatusCode::OK) + .content_type(CONTENT_TYPE) + .del_cookie(&cookie) + .body(format!("

?enable=false; unsetting `{}` mode cookie

", ALPHA_COOKIE_NAME)) + } + } +} diff --git a/src/endpoints/misc/mod.rs b/src/endpoints/misc/mod.rs new file mode 100644 index 0000000000..c43dd66c3d --- /dev/null +++ b/src/endpoints/misc/mod.rs @@ -0,0 +1 @@ +pub mod enable_alpha; \ No newline at end of file diff --git a/src/endpoints/mod.rs b/src/endpoints/mod.rs index d21a0a3a4b..a3cbbff247 100644 --- a/src/endpoints/mod.rs +++ b/src/endpoints/mod.rs @@ -1,3 +1,4 @@ pub mod default_route_404; +pub mod misc; pub mod root_index; pub mod users; \ No newline at end of file diff --git a/src/endpoints/root_index.rs b/src/endpoints/root_index.rs index aa1c45e309..3f49e31b9f 100644 --- a/src/endpoints/root_index.rs +++ b/src/endpoints/root_index.rs @@ -1,10 +1,10 @@ use actix_http::http::StatusCode; use actix_web::{HttpResponse, HttpRequest, Responder, get}; -use log::info; +use log::debug; #[get("/")] pub async fn get_root_index() -> impl Responder { - info!("GET /"); + debug!("GET /"); // NB: Google load balancer hits this a lot, and it spams. HttpResponse::build(StatusCode::OK) .content_type("text/html; charset=utf-8") .body("

hello friend

") diff --git a/src/main.rs b/src/main.rs index f21c9aec35..bf3c09f02a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,7 @@ use crate::util::session_checker::SessionChecker; use crate::endpoints::users::session_info::session_info_handler; use crate::endpoints::root_index::get_root_index; use crate::endpoints::default_route_404::default_route_404; +use crate::endpoints::misc::enable_alpha::enable_alpha; const DEFAULT_BIND_ADDRESS : &'static str = "0.0.0.0:12345"; const DEFAULT_RUST_LOG: &'static str = "debug,actix_web=info"; @@ -64,16 +65,22 @@ async fn main() -> AnyhowResult<()> { info!("Reading env vars and setting up utils..."); let bind_address = easyenv::get_env_string_or_default("BIND_ADDRESS", DEFAULT_BIND_ADDRESS); + let num_workers = easyenv::get_env_num("NUM_WORKERS", 4)?; let hmac_secret = easyenv::get_env_string_or_default("COOKIE_SECRET", "notsecret"); let cookie_domain = easyenv::get_env_string_or_default("COOKIE_DOMAIN", ".vo.codes"); + let cookie_secure = easyenv::get_env_bool_or_default("COOKIE_SECURE", true); + let cookie_http_only = easyenv::get_env_bool_or_default("COOKIE_HTTP_ONLY", true); let cookie_manager = CookieManager::new(&cookie_domain, &hmac_secret); let session_checker = SessionChecker::new(&cookie_manager); let server_state = ServerState { env_config: EnvConfig { - num_workers: 4, + num_workers, bind_address, + cookie_domain, + cookie_secure, + cookie_http_only, }, hostname: server_hostname, mysql_pool: pool, @@ -160,6 +167,7 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()> .route(web::head().to(|| HttpResponse::Ok())) ) .service(get_root_index) + .service(enable_alpha) .default_service( web::route().to(default_route_404)) }) .bind(bind_address)? diff --git a/src/server_state.rs b/src/server_state.rs index 6069821760..7cc0801642 100644 --- a/src/server_state.rs +++ b/src/server_state.rs @@ -22,4 +22,7 @@ pub struct EnvConfig { // Number of thread workers. pub num_workers: usize, pub bind_address: String, + pub cookie_domain: String, + pub cookie_secure: bool, + pub cookie_http_only: bool, }