/* * This file is part of laurelin/api * Copyright (C) 2023 Jonni Liljamo * * Licensed under GPL-3.0-only. * See LICENSE for licensing information. */ use actix_session::{ config::{PersistentSession, SessionLifecycle, TtlExtensionPolicy}, storage::RedisActorSessionStore, Session, SessionMiddleware, }; use actix_web::{ cookie::{time::Duration, Key}, get, middleware::Logger, web, App, HttpResponse, HttpServer, Responder, }; use diesel::{ self, r2d2::{self, ConnectionManager}, PgConnection, }; use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness}; type PgPool = r2d2::Pool>; const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); #[get("/api/ping")] async fn ping() -> impl Responder { HttpResponse::Ok().body("pong") } #[get("/api/ping_sec")] async fn ping_sec(session: Session) -> impl Responder { let session_validation = session::validate_session(&session); match session_validation { Err(err) => err, Ok(user_id) => { // NOTE: this is where one would spawn an action to do... something. // the user id can be used to check if the user can, e.g. start a game. return HttpResponse::Ok().body(format!("pong_sec for user_id: '{}'", user_id)); } } } fn run_migrations(conn: &mut PgConnection) { conn.run_pending_migrations(MIGRATIONS).unwrap(); } mod actions; mod handlers; mod session; #[actix_web::main] async fn main() -> std::io::Result<()> { pretty_env_logger::init(); // timestamp status_code latency remote_ip request_details let log_format = "%t | %s | %Dms | %a | \"%r\""; // setup db pool let db_url = std::env::var("LAURELIN_DB_URL").expect("LAURELIN_DB_URL"); let manager = ConnectionManager::::new(db_url); let pg_pool = r2d2::Pool::builder() .build(manager) .expect("failed to create pool"); // run migrations log::info!("running migrations"); run_migrations(&mut pg_pool.get().unwrap()); let redis_url = std::env::var("LAURELIN_REDIS_URL").expect("LAURELIN_REDIS_URL"); let cookie_key = std::env::var("LAURELIN_COOKIE_KEY").expect("LAURELIN_COOKIE_KEY"); HttpServer::new(move || { App::new() .app_data(web::Data::new(pg_pool.clone())) .wrap(Logger::new(log_format)) .wrap( SessionMiddleware::builder( RedisActorSessionStore::new(&redis_url), Key::from(cookie_key.as_bytes()), ) .session_lifecycle(SessionLifecycle::PersistentSession( PersistentSession::default() .session_ttl(Duration::days(30)) .session_ttl_extension_policy(TtlExtensionPolicy::OnStateChanges), )) .build(), ) .service(ping) .service(ping_sec) .service(handlers::info) .service(handlers::user::info) .service(handlers::user::create) .service(handlers::user::login) .service(handlers::user::logout) .service(handlers::game::create) .service(handlers::game::all_forming) .service(handlers::game::my_games) .service(handlers::game::info) .service(handlers::game::patch) }) .bind(("0.0.0.0", 8080))? .run() .await }