-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
910 additions
and
123 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
use std::sync::{Arc, Mutex}; | ||
|
||
use oauth2::basic::BasicClient; | ||
use redis::aio::MultiplexedConnection; | ||
use redis_work_queue::KeyPrefix; | ||
use serde::{Deserialize, Serialize}; | ||
use sqlx::PgPool; | ||
use utoipa::ToSchema; | ||
|
||
#[derive(Clone)] | ||
pub struct AppState { | ||
pub db: PgPool, | ||
pub redis: Arc<Mutex<MultiplexedConnection>>, | ||
pub work_queue_key: KeyPrefix, | ||
pub google_oauth: BasicClient, | ||
pub google_userinfo_url: String, | ||
pub csh_oauth: BasicClient, | ||
pub csh_userinfo_url: String, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, sqlx::Type, ToSchema, Clone)] | ||
#[serde(rename_all = "camelCase")] | ||
pub struct UserData { | ||
pub id: String, | ||
pub realm: String, | ||
pub name: String, | ||
pub email: String, | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub struct SimpleRiderChange { | ||
pub event_id: i32, | ||
pub car_id: i32, | ||
pub rider_id: String, | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
pub struct MultipleRiderChange { | ||
pub event_id: i32, | ||
pub car_id: i32, | ||
pub old_riders: Vec<String>, | ||
pub new_riders: Vec<String>, | ||
} | ||
|
||
#[derive(Serialize, Deserialize)] | ||
#[serde(tag = "type")] | ||
pub enum RedisJob { | ||
Join(SimpleRiderChange), | ||
Leave(SimpleRiderChange), | ||
RiderUpdate(MultipleRiderChange), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,34 @@ | ||
use actix_session::storage::CookieSessionStore; | ||
use actix_session::SessionMiddleware; | ||
use actix_web::cookie::Key; | ||
use actix_web::{middleware::Logger, web, App, HttpResponse, HttpServer, Responder}; | ||
use anyhow::anyhow; | ||
use base64::prelude::*; | ||
use include_dir::{include_dir, Dir}; | ||
use log::info; | ||
use oauth2::basic::BasicClient; | ||
use sqlx::{postgres::PgPoolOptions, PgPool}; | ||
use std::env; | ||
|
||
mod api; | ||
pub mod api; | ||
pub mod app; | ||
mod auth; | ||
//mod pings; // Undo this when developing it | ||
|
||
#[derive(Clone)] | ||
struct AppState { | ||
db: PgPool, | ||
google_oauth: BasicClient, | ||
google_userinfo_url: String, | ||
csh_oauth: BasicClient, | ||
csh_userinfo_url: String, | ||
} | ||
|
||
// Embed the 'static' directory into the binary | ||
static STATIC_DIR: Dir<'_> = include_dir!("$CARGO_MANIFEST_DIR/src/frontend/dist"); | ||
|
||
async fn serve_file(path: web::Path<String>) -> impl Responder { | ||
let file_path = path.into_inner(); | ||
if let Some(file) = STATIC_DIR.get_file(&file_path) { | ||
let content = file.contents(); | ||
let mime = mime_guess::from_path(&file_path).first_or_octet_stream(); | ||
HttpResponse::Ok().content_type(mime.as_ref()).body(content) | ||
} else { | ||
HttpResponse::NotFound().body("File not found") | ||
} | ||
pub mod pings; | ||
mod server; | ||
mod worker; | ||
|
||
use clap::{Parser, Subcommand}; | ||
|
||
#[derive(Parser)] | ||
#[command(name = "App")] | ||
#[command(about = "An application with async server and worker subcommands", long_about = None)] | ||
struct Cli { | ||
#[command(subcommand)] | ||
command: Commands, | ||
} | ||
|
||
async fn serve_index() -> impl Responder { | ||
if let Some(file) = STATIC_DIR.get_file("index.html") { | ||
let content = file.contents(); | ||
let mime = mime_guess::from_path("index.html").first_or_octet_stream(); | ||
HttpResponse::Ok().content_type(mime.as_ref()).body(content) | ||
} else { | ||
HttpResponse::NotFound().body("File not found") | ||
} | ||
#[derive(Subcommand)] | ||
enum Commands { | ||
/// Start the async server | ||
Server, | ||
/// Start the async worker | ||
Worker, | ||
} | ||
|
||
#[actix_web::main] | ||
#[tokio::main] | ||
async fn main() -> std::io::Result<()> { | ||
env_logger::init(); | ||
dotenv::dotenv().ok(); | ||
|
||
let host = env::var("HOST").unwrap_or("127.0.0.1".to_string()); | ||
let host_inner = host.clone(); | ||
let port: i32 = match &env::var("PORT").map(|port| port.parse()) { | ||
Ok(Ok(p)) => *p, | ||
Ok(Err(_)) => 8080, | ||
Err(_) => 8080, | ||
}; | ||
|
||
let db_pool = PgPoolOptions::new() | ||
.max_connections(5) | ||
.connect(&env::var("DATABASE_URL").expect("DATABASE_URL must be set")) | ||
.await | ||
.expect("Failed to create pool"); | ||
let cli = Cli::parse(); | ||
|
||
let session_key = env::var("SESSION_KEY") | ||
.map_err(|e| anyhow!("Failed to get Env Var: {}", e)) | ||
.and_then(|key64| { | ||
BASE64_STANDARD | ||
.decode(key64) | ||
.map_err(|e| anyhow!("Failed to decode session key: {}", e)) | ||
}) | ||
.map(|key| Key::from(&key)) | ||
.unwrap_or(Key::generate()); | ||
|
||
info!("Starting server at http://{host}:{port}"); | ||
HttpServer::new(move || { | ||
let (google_client, csh_client) = auth::get_clients(&host_inner, port); | ||
|
||
App::new() | ||
.app_data(web::Data::new(AppState { | ||
db: db_pool.clone(), | ||
google_oauth: google_client, | ||
google_userinfo_url: "https://openidconnect.googleapis.com/v1/userinfo".to_string(), | ||
csh_oauth: csh_client, | ||
csh_userinfo_url: env::var("CSH_USERINFO_URL") | ||
.expect("Missing Userinfo URL for CSH Auth"), | ||
})) | ||
.wrap( | ||
SessionMiddleware::builder(CookieSessionStore::default(), session_key.clone()) | ||
.cookie_secure(env::var("DEVELOPMENT").is_err()) | ||
.build(), | ||
) | ||
.wrap(Logger::default()) | ||
.service(api::scope()) | ||
.route("/", web::get().to(serve_index)) | ||
.route("/history", web::get().to(serve_index)) | ||
.route("/login", web::get().to(serve_index)) | ||
.route("/{filename:.*}", web::get().to(serve_file)) | ||
}) | ||
.bind(format!("{host}:{port}"))? | ||
.run() | ||
.await | ||
match &cli.command { | ||
Commands::Server => server::main().await, | ||
Commands::Worker => worker::main().await, | ||
} | ||
} |
Oops, something went wrong.