From 7223c99da99e68fea869c26b2f8378fb7c7ad9fd Mon Sep 17 00:00:00 2001 From: core Date: Tue, 28 Nov 2023 11:26:06 -0500 Subject: [PATCH] remove old API in prep for replacement with new Go API --- api/Cargo.toml | 34 ---- api/config.toml | 22 --- api/src/config.rs | 90 --------- api/src/error.rs | 116 ----------- api/src/main.rs | 82 -------- api/src/routes/beamin.rs | 107 ----------- api/src/routes/beamout.rs | 92 --------- api/src/routes/callback.rs | 181 ------------------ api/src/routes/mod.rs | 5 - api/src/routes/select_realm.rs | 50 ----- api/src/routes/server_list.rs | 16 -- api/starkingdoms_api_entities/Cargo.toml | 9 - .../src/entity/mod.rs | 7 - .../src/entity/prelude.rs | 5 - .../src/entity/user.rs | 27 --- .../src/entity/user_auth_realm.rs | 41 ---- .../src/entity/user_savefile.rs | 34 ---- api/starkingdoms_api_entities/src/lib.rs | 1 - api/starkingdoms_api_migration/.env | 1 - api/starkingdoms_api_migration/Cargo.toml | 24 --- api/starkingdoms_api_migration/README.md | 41 ---- api/starkingdoms_api_migration/src/lib.rs | 18 -- .../m20230417_162824_create_table_users.rs | 40 ---- ...17_164240_create_table_user_auth_realms.rs | 52 ----- ...m20230420_144333_create_table_user_data.rs | 53 ----- api/starkingdoms_api_migration/src/main.rs | 6 - api/static/all.css | 0 api/templates/base.tera | 14 -- api/templates/select_realm.tera | 11 -- 29 files changed, 1179 deletions(-) delete mode 100644 api/Cargo.toml delete mode 100644 api/config.toml delete mode 100644 api/src/config.rs delete mode 100644 api/src/error.rs delete mode 100644 api/src/main.rs delete mode 100644 api/src/routes/beamin.rs delete mode 100644 api/src/routes/beamout.rs delete mode 100644 api/src/routes/callback.rs delete mode 100644 api/src/routes/mod.rs delete mode 100644 api/src/routes/select_realm.rs delete mode 100644 api/src/routes/server_list.rs delete mode 100644 api/starkingdoms_api_entities/Cargo.toml delete mode 100644 api/starkingdoms_api_entities/src/entity/mod.rs delete mode 100644 api/starkingdoms_api_entities/src/entity/prelude.rs delete mode 100644 api/starkingdoms_api_entities/src/entity/user.rs delete mode 100644 api/starkingdoms_api_entities/src/entity/user_auth_realm.rs delete mode 100644 api/starkingdoms_api_entities/src/entity/user_savefile.rs delete mode 100644 api/starkingdoms_api_entities/src/lib.rs delete mode 100644 api/starkingdoms_api_migration/.env delete mode 100644 api/starkingdoms_api_migration/Cargo.toml delete mode 100644 api/starkingdoms_api_migration/README.md delete mode 100644 api/starkingdoms_api_migration/src/lib.rs delete mode 100644 api/starkingdoms_api_migration/src/m20230417_162824_create_table_users.rs delete mode 100644 api/starkingdoms_api_migration/src/m20230417_164240_create_table_user_auth_realms.rs delete mode 100644 api/starkingdoms_api_migration/src/m20230420_144333_create_table_user_data.rs delete mode 100644 api/starkingdoms_api_migration/src/main.rs delete mode 100644 api/static/all.css delete mode 100644 api/templates/base.tera delete mode 100644 api/templates/select_realm.tera diff --git a/api/Cargo.toml b/api/Cargo.toml deleted file mode 100644 index 008f830e6935920db529b1b7503563dea539e0b9..0000000000000000000000000000000000000000 --- a/api/Cargo.toml +++ /dev/null @@ -1,34 +0,0 @@ -[package] -name = "starkingdoms-api" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -actix-web = "4" # Web framework -actix-request-identifier = "4" # Web framework -actix-files = "0.6" # Web framework -actix-cors = "0.6.4" # Web framework - -serde = { version = "1", features = ["derive"] } # Serialization and deserialization - -once_cell = "1" # Config -toml = "0.7" # Config / Serialization and deserialization - -log = "0.4" # Logging -simple_logger = "4" # Logging - -sea-orm = { version = "^0", features = [ "sqlx-postgres", "runtime-actix-rustls", "macros" ]} # Database -starkingdoms_api_migration = { version = "0.1.0", path = "starkingdoms_api_migration" } # Database -starkingdoms_api_entities = { version = "0.1.0", path = "starkingdoms_api_entities" } # Database - -ulid = "1.0.0" # Identifiers - -tera = "1" # Templates - -jwt = { version = "0.16", features = ["openssl"] } # Auth -openssl = "0.10" # Auth -reqwest = "0.11" # Auth -hmac = "0.12.1" # Auth -sha2 = "0.10.6" # Auth diff --git a/api/config.toml b/api/config.toml deleted file mode 100644 index 12a0a920384d39718efb29ac8d10834aaec95ea6..0000000000000000000000000000000000000000 --- a/api/config.toml +++ /dev/null @@ -1,22 +0,0 @@ -game = "localhost:5173" -internal_tokens = ["01GY803PVK7YJKXZYWFTK6DS1Y-01GY8040ZQY9SG29DXY4HZ4EPD"] -jwt_signing_secret = "544adbc8144d375d581a1622a4f0cbcf92f006a156ef8b9d4afac6410f51f73c" -base = "localhost:8080" -servers = ["http://localhost:3000"] - -[server] -listen = "0.0.0.0:8080" - -[realms.discord] -authorize_url = "https://api.e3t.cc/auth/discord/authorize.php" -public_key = "-----BEGIN PUBLIC KEY-----\nMIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgHBcZsCM6ebFDCp3dFc+3EOzLw8B\n+fR+9Tx6S/lXOTghk49s7yaxza/zVRPxWaMqyjegfRCEepgV++jbWzBib7bhy91M\n+zlRbeZ9rf++N30Nf4R/XAnUAmhAHt8TzDC08DNQNYAFz37+r4EZlY7APHyND4qU\nd8w3qB95v/wMVB6nAgMBAAE=\n-----END PUBLIC KEY-----" -issuer = "https://api.e3t.cc" - -[database] -url = "postgres://postgres@localhost/starkingdoms" - -[endpoints] -allowed_return_endpoints = [ - "127.0.0.1:5173", - "starkingdoms.tk" -] diff --git a/api/src/config.rs b/api/src/config.rs deleted file mode 100644 index 792358a0d6e1dace41039fc3456d6d9bbbac8396..0000000000000000000000000000000000000000 --- a/api/src/config.rs +++ /dev/null @@ -1,90 +0,0 @@ -use log::error; -use once_cell::sync::Lazy; -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use std::fs; -use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4}; - -pub static CONFIG: Lazy = Lazy::new(|| { - let config_str = match fs::read_to_string("/etc/starkingdoms/config.toml") { - Ok(str) => str, - Err(e) => { - error!("Unable to read config file: {}", e); - std::process::exit(1); - } - }; - - match toml::from_str(&config_str) { - Ok(cfg) => cfg, - Err(e) => { - error!("Unable to parse config file: {}", e); - std::process::exit(1); - } - } -}); - -#[derive(Serialize, Debug, Deserialize)] -pub struct StarkingdomsApiConfig { - pub database: StarkingdomsApiConfigDatabase, - pub server: StarkingdomsApiConfigServer, - pub internal_tokens: Vec, - pub jwt_signing_secret: String, - pub base: String, - pub game: String, - pub realms: HashMap, - pub servers: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct StarkingdomsApiConfigDatabase { - pub url: String, - #[serde(default = "max_connections_default")] - pub max_connections: u32, - #[serde(default = "min_connections_default")] - pub min_connections: u32, - #[serde(default = "time_defaults")] - pub connect_timeout: u64, - #[serde(default = "time_defaults")] - pub acquire_timeout: u64, - #[serde(default = "time_defaults")] - pub idle_timeout: u64, - #[serde(default = "time_defaults")] - pub max_lifetime: u64, - #[serde(default = "sqlx_logging_default")] - pub sqlx_logging: bool, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct StarkingdomsApiConfigServer { - #[serde(default = "socketaddr_8080")] - pub bind: SocketAddr, -} - -/* -authorize-url = "https://api.e3t.cc/auth/discord/authorize.php" -public-key-url = "https://api.e3t.cc/auth/discord/public-key.txt" -issuer = "https://api.e3t.cc" - */ - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct StarkingdomsApiConfigRealm { - pub authorize_url: String, - pub public_key: String, - pub issuer: String, -} - -fn max_connections_default() -> u32 { - 100 -} -fn min_connections_default() -> u32 { - 5 -} -fn time_defaults() -> u64 { - 8 -} -fn sqlx_logging_default() -> bool { - true -} -fn socketaddr_8080() -> SocketAddr { - SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from([0, 0, 0, 0]), 8080)) -} diff --git a/api/src/error.rs b/api/src/error.rs deleted file mode 100644 index 953ffc003a3cafd83cc87052df77945cc4f0ee76..0000000000000000000000000000000000000000 --- a/api/src/error.rs +++ /dev/null @@ -1,116 +0,0 @@ -use actix_web::error::{JsonPayloadError, PayloadError}; -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct APIErrorsResponse { - pub errors: Vec, -} -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct APIError { - pub code: String, - pub message: String, - #[serde(skip_serializing_if = "is_none")] - #[serde(default)] - pub path: Option, -} - -fn is_none(o: &Option) -> bool { - o.is_none() -} - -impl From<&JsonPayloadError> for APIError { - fn from(value: &JsonPayloadError) -> Self { - match value { - JsonPayloadError::OverflowKnownLength { length, limit } => { - APIError { - code: "ERR_PAYLOAD_OVERFLOW_KNOWN_LENGTH".to_string(), - message: format!("Payload size is bigger than allowed & content length header set. (length: {}, limit: {})", length, limit), - path: None - } - }, - JsonPayloadError::Overflow { limit } => { - APIError { - code: "ERR_PAYLOAD_OVERFLOW".to_string(), - message: format!("Payload size is bigger than allowed but no content-length header is set. (limit: {})", limit), - path: None - } - }, - JsonPayloadError::ContentType => { - APIError { - code: "ERR_NOT_JSON".to_string(), - message: "Content-Type header not set to expected application/json".to_string(), - path: None, - } - }, - JsonPayloadError::Deserialize(e) => { - APIError { - code: "ERR_JSON_DESERIALIZE".to_string(), - message: format!("Error deserializing JSON: {}", e), - path: None, - } - }, - JsonPayloadError::Serialize(e) => { - APIError { - code: "ERR_JSON_SERIALIZE".to_string(), - message: format!("Error serializing JSON: {}", e), - path: None, - } - }, - JsonPayloadError::Payload(e) => { - e.into() - }, - _ => { - APIError { - code: "ERR_UNKNOWN_ERROR".to_string(), - message: "An unknown error has occured".to_string(), - path: None, - } - } - } - } -} - -impl From<&PayloadError> for APIError { - fn from(value: &PayloadError) -> Self { - match value { - PayloadError::Incomplete(e) => APIError { - code: "ERR_UNEXPECTED_EOF".to_string(), - message: match e { - None => "Payload reached EOF but was incomplete".to_string(), - Some(e) => format!("Payload reached EOF but was incomplete: {}", e), - }, - path: None, - }, - PayloadError::EncodingCorrupted => APIError { - code: "ERR_CORRUPTED_PAYLOAD".to_string(), - message: "Payload content encoding corrupted".to_string(), - path: None, - }, - PayloadError::Overflow => APIError { - code: "ERR_PAYLOAD_OVERFLOW".to_string(), - message: "Payload reached size limit".to_string(), - path: None, - }, - PayloadError::UnknownLength => APIError { - code: "ERR_PAYLOAD_UNKNOWN_LENGTH".to_string(), - message: "Unable to determine payload length".to_string(), - path: None, - }, - PayloadError::Http2Payload(e) => APIError { - code: "ERR_HTTP2_ERROR".to_string(), - message: format!("HTTP/2 error: {}", e), - path: None, - }, - PayloadError::Io(e) => APIError { - code: "ERR_IO_ERROR".to_string(), - message: format!("I/O error: {}", e), - path: None, - }, - _ => APIError { - code: "ERR_UNKNOWN_ERROR".to_string(), - message: "An unknown error has occured".to_string(), - path: None, - }, - } - } -} diff --git a/api/src/main.rs b/api/src/main.rs deleted file mode 100644 index 664c0743161b95d0036a8474012edad5b241dc62..0000000000000000000000000000000000000000 --- a/api/src/main.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::config::CONFIG; -use crate::error::{APIError, APIErrorsResponse}; -use actix_cors::Cors; -use actix_request_identifier::RequestIdentifier; -use actix_web::http::header::HeaderValue; -use actix_web::web::{Data, JsonConfig}; -use actix_web::{App, HttpResponse, HttpServer}; -use log::{info, Level}; -use sea_orm::{ConnectOptions, Database, DatabaseConnection}; -use starkingdoms_api_migration::{Migrator, MigratorTrait}; -use std::error::Error; -use std::time::Duration; -use tera::Tera; - -pub mod config; -pub mod error; -pub mod routes; - -pub struct AppState { - pub conn: DatabaseConnection, - pub templates: Tera, -} - -#[actix_web::main] -async fn main() -> Result<(), Box> { - simple_logger::init_with_level(Level::Debug).unwrap(); - - info!("Connecting to database at {}...", CONFIG.database.url); - - let mut opt = ConnectOptions::new(CONFIG.database.url.clone()); - opt.max_connections(CONFIG.database.max_connections) - .min_connections(CONFIG.database.min_connections) - .connect_timeout(Duration::from_secs(CONFIG.database.connect_timeout)) - .acquire_timeout(Duration::from_secs(CONFIG.database.acquire_timeout)) - .idle_timeout(Duration::from_secs(CONFIG.database.idle_timeout)) - .max_lifetime(Duration::from_secs(CONFIG.database.max_lifetime)) - .sqlx_logging(CONFIG.database.sqlx_logging) - .sqlx_logging_level(log::LevelFilter::Info); - - let db = Database::connect(opt).await?; - - info!("Performing database migration..."); - Migrator::up(&db, None).await?; - - info!("Loading templates..."); - let tera = Tera::new("templates/**/*.tera")?; - - let data = Data::new(AppState { - conn: db, - templates: tera, - }); - - HttpServer::new(move || { - App::new() - .wrap(Cors::permissive()) - .app_data(data.clone()) - .app_data(JsonConfig::default().error_handler(|err, _req| { - let api_error: APIError = (&err).into(); - actix_web::error::InternalError::from_response( - err, - HttpResponse::BadRequest().json(APIErrorsResponse { - errors: vec![api_error], - }), - ) - .into() - })) - .wrap(RequestIdentifier::with_generator(|| { - HeaderValue::from_str(&ulid::Ulid::new().to_string()).unwrap() - })) - .service(routes::select_realm::select_realm) - .service(routes::callback::callback) - .service(routes::beamin::beam_in) - .service(routes::beamout::beam_out) - .service(routes::server_list::server_list) - .service(actix_files::Files::new("/static", "static")) - }) - .bind(CONFIG.server.bind)? - .run() - .await?; - - Ok(()) -} diff --git a/api/src/routes/beamin.rs b/api/src/routes/beamin.rs deleted file mode 100644 index 3ae385a566d2bbc8afac1251e3f2f42b7a9cff6d..0000000000000000000000000000000000000000 --- a/api/src/routes/beamin.rs +++ /dev/null @@ -1,107 +0,0 @@ -use crate::config::CONFIG; -use crate::error::{APIError, APIErrorsResponse}; -use crate::AppState; -use actix_web::web::{Data, Json}; -use actix_web::{post, HttpResponse}; -use hmac::digest::KeyInit; -use hmac::Hmac; -use jwt::VerifyWithKey; -use log::error; -use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder}; -use serde::{Deserialize, Serialize}; -use sha2::Sha256; -use starkingdoms_protocol::api::APISavedPlayerData; -use std::collections::BTreeMap; - -#[derive(Serialize, Deserialize)] -pub struct BeaminRequest { - pub api_token: String, - pub user_auth_realm_id: String, - pub user_auth_token: String, -} - -#[derive(Serialize, Deserialize)] -pub struct BeaminResponse { - pub save_id: String, - pub save: APISavedPlayerData, -} - -#[post("/beamin")] -pub async fn beam_in(data: Json, state: Data) -> HttpResponse { - if !CONFIG.internal_tokens.contains(&data.api_token) { - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_BAD_TOKEN".to_string(), - message: "Missing or invalid api token".to_string(), - path: None, - }], - }); - } - - let key: Hmac = Hmac::new_from_slice(CONFIG.jwt_signing_secret.as_bytes()).unwrap(); - let token: BTreeMap = match data.user_auth_token.verify_with_key(&key) { - Ok(t) => t, - Err(e) => { - error!("verifying error: {}", e); - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_BAD_TOKEN".to_string(), - message: "Missing or invalid user token".to_string(), - path: None, - }], - }); - } - }; - - if !token.contains_key("user") || !token.contains_key("nonce") { - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_BAD_TOKEN".to_string(), - message: "Missing or invalid user token (missing scopes)".to_string(), - path: None, - }], - }); - } - - let user_id = token.get("user").unwrap(); - - let user_savefile: Vec = - match starkingdoms_api_entities::entity::user_savefile::Entity::find() - .filter(starkingdoms_api_entities::entity::user_savefile::Column::User.eq(user_id)) - .order_by_desc(starkingdoms_api_entities::entity::user_savefile::Column::Timestamp) - .all(&state.conn) - .await - { - Ok(sf) => sf, - Err(e) => { - error!("database error: {}", e); - return HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_DB_ERROR".to_string(), - message: "Unable to fetch user savefiles".to_string(), - path: None, - }], - }); - } - }; - if user_savefile.is_empty() { - return HttpResponse::NoContent().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_NO_SAVES".to_string(), - message: "This user has no savefiles".to_string(), - path: None, - }], - }); - } - - let save = &user_savefile[0]; - let save_id = &save.id; - let save_data_str = &save.data; - let save_data: APISavedPlayerData = - toml::from_str(save_data_str).expect("database contained corrupted player save data"); - - HttpResponse::Ok().json(BeaminResponse { - save_id: save_id.clone(), - save: save_data, - }) -} diff --git a/api/src/routes/beamout.rs b/api/src/routes/beamout.rs deleted file mode 100644 index f2866999ed4a176591429a4b7c5f7b3fcd684f80..0000000000000000000000000000000000000000 --- a/api/src/routes/beamout.rs +++ /dev/null @@ -1,92 +0,0 @@ -use crate::config::CONFIG; -use crate::error::{APIError, APIErrorsResponse}; -use crate::AppState; -use actix_web::web::{Data, Json}; -use actix_web::{post, HttpResponse}; -use hmac::digest::KeyInit; -use hmac::Hmac; -use jwt::VerifyWithKey; -use log::error; -use sea_orm::{ActiveModelTrait, IntoActiveModel}; -use serde::{Deserialize, Serialize}; -use sha2::Sha256; -use starkingdoms_protocol::api::APISavedPlayerData; -use std::collections::BTreeMap; -use std::time::{SystemTime, UNIX_EPOCH}; -use ulid::Ulid; - -#[derive(Serialize, Deserialize)] -pub struct BeamoutRequest { - pub api_token: String, - pub user_auth_realm_id: String, - pub user_auth_token: String, - pub data: APISavedPlayerData, -} - -#[derive(Serialize, Deserialize)] -pub struct BeamoutResponse {} - -#[post("/beamout")] -pub async fn beam_out(data: Json, state: Data) -> HttpResponse { - if !CONFIG.internal_tokens.contains(&data.api_token) { - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_BAD_TOKEN".to_string(), - message: "Missing or invalid api token".to_string(), - path: None, - }], - }); - } - - let key: Hmac = Hmac::new_from_slice(CONFIG.jwt_signing_secret.as_bytes()).unwrap(); - let token: BTreeMap = match data.user_auth_token.verify_with_key(&key) { - Ok(t) => t, - Err(e) => { - error!("verifying error: {}", e); - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_BAD_TOKEN".to_string(), - message: "Missing or invalid user token".to_string(), - path: None, - }], - }); - } - }; - - if !token.contains_key("user") || !token.contains_key("nonce") { - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_BAD_TOKEN".to_string(), - message: "Missing or invalid user token (missing scopes)".to_string(), - path: None, - }], - }); - } - - let saved_data = toml::to_string(&data.data).unwrap(); - let savefile_model = starkingdoms_api_entities::entity::user_savefile::Model { - id: format!("save-{}", Ulid::new().to_string()), - user: token.get("user").unwrap().clone(), - data: saved_data, - timestamp: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs() as i64, - }; - let savefile_active_model = savefile_model.into_active_model(); - match savefile_active_model.insert(&state.conn).await { - Ok(_) => (), - Err(e) => { - error!("database error: {}", e); - return HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_DB_ERROR".to_string(), - message: "database failure".to_string(), - path: None, - }], - }); - } - } - - HttpResponse::Ok().json(BeamoutResponse {}) -} diff --git a/api/src/routes/callback.rs b/api/src/routes/callback.rs deleted file mode 100644 index 2cbbf0af405b43437a2c67e0f48ea0261c3b37b6..0000000000000000000000000000000000000000 --- a/api/src/routes/callback.rs +++ /dev/null @@ -1,181 +0,0 @@ -use crate::config::CONFIG; -use crate::error::{APIError, APIErrorsResponse}; -use crate::AppState; -use actix_web::web::{Data, Query}; -use actix_web::{get, HttpResponse}; -use hmac::digest::KeyInit; -use hmac::Hmac; -use jwt::{PKeyWithDigest, SignWithKey, VerifyWithKey}; -use log::{debug, error}; -use openssl::hash::MessageDigest; -use openssl::pkey::PKey; -use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter}; -use serde::Deserialize; -use sha2::Sha256; -use starkingdoms_api_entities::entity; -use std::collections::BTreeMap; -use std::time::{SystemTime, UNIX_EPOCH}; -use ulid::Ulid; - -#[derive(Deserialize)] -pub struct CallbackQueryParams { - pub token: String, - pub realm: String, -} - -#[get("/callback")] -pub async fn callback(query: Query, state: Data) -> HttpResponse { - // verify token from auth provider API - - // 1. load the public key - let realm = match CONFIG.realms.get(&query.realm) { - Some(r) => r, - None => { - error!("realm not found"); - return HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_UNKNOWN_REALM".to_string(), - message: "Unknown realm".to_string(), - path: None, - }], - }); - } - }; - - let rs256_pub_key = PKeyWithDigest { - digest: MessageDigest::sha256(), - key: PKey::public_key_from_pem(realm.public_key.as_bytes()).unwrap(), - }; - - let token: BTreeMap = match query.token.verify_with_key(&rs256_pub_key) { - Ok(tkn) => tkn, - Err(e) => { - error!("[callback] token verify error: {}", e); - return generic_unauthorized(); - } - }; - - let realm = match token.get("realm").ok_or(generic_unauthorized()) { - Ok(r) => r, - Err(e) => return e, - }; - let realm_local_id = match token.get("realm_native_id").ok_or(generic_unauthorized()) { - Ok(r) => r, - Err(e) => return e, - }; - - debug!( - "got authenticated realm native authorization: authenticated as {}:{}", - realm, realm_local_id - ); - - // see if a user on this realm already exists - let maybe_user = match entity::user_auth_realm::Entity::find() - .filter(entity::user_auth_realm::Column::RealmNativeId.eq(realm_local_id.clone())) - .filter(entity::user_auth_realm::Column::Realm.eq(realm.clone())) - .one(&state.conn) - .await - { - Ok(r) => r, - Err(e) => { - error!("database error: {}", e); - return HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_DB_ERROR".to_string(), - message: "Database error".to_string(), - path: None, - }], - }); - } - }; - - if let Some(user) = maybe_user { - let key: Hmac = Hmac::new_from_slice(CONFIG.jwt_signing_secret.as_bytes()).unwrap(); - let mut claims = BTreeMap::new(); - claims.insert("user", user.id.clone()); - claims.insert("nonce", Ulid::new().to_string()); - let token_str = claims.sign_with_key(&key).unwrap(); - let auth_url = format!("{}/?token={}&user={}", CONFIG.game, token_str, user.id); - return HttpResponse::Found() - .append_header(("Location", auth_url)) - .finish(); - } - - // create the user - let new_user = entity::user::Model { - id: format!("user-{}", Ulid::new().to_string()), - username: Ulid::new().to_string(), - created_on: SystemTime::now() - .duration_since(UNIX_EPOCH) - .unwrap() - .as_secs() as i64, - }; - let new_user_realm = entity::user_auth_realm::Model { - id: format!( - "{}-{}:{}", - new_user.id.clone(), - realm.clone(), - realm_local_id.clone() - ), - realm: realm.clone(), - realm_native_id: realm_local_id.clone(), - user: new_user.id.clone(), - }; - - let key: Hmac = Hmac::new_from_slice(CONFIG.jwt_signing_secret.as_bytes()).unwrap(); - let mut claims = BTreeMap::new(); - claims.insert("user", new_user.id.clone()); - claims.insert("nonce", Ulid::new().to_string()); - let token_str = claims.sign_with_key(&key).unwrap(); - let auth_url = format!( - "{}/?token={}&user={}", - CONFIG.game, - token_str, - new_user.id.clone() - ); - - let new_user_active_model = new_user.into_active_model(); - let new_user_realm_active_model = new_user_realm.into_active_model(); - - match new_user_active_model.insert(&state.conn).await { - Ok(_) => (), - Err(e) => { - error!("database error: {}", e); - return HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_DB_ERROR".to_string(), - message: "Database error".to_string(), - path: None, - }], - }); - } - } - - match new_user_realm_active_model.insert(&state.conn).await { - Ok(_) => (), - Err(e) => { - error!("database error: {}", e); - return HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_DB_ERROR".to_string(), - message: "Database error".to_string(), - path: None, - }], - }); - } - } - - HttpResponse::Found() - .append_header(("Location", auth_url)) - .finish() -} - -fn generic_unauthorized() -> HttpResponse { - HttpResponse::Unauthorized().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_INVALID_STATE".to_string(), - message: "Unknown/invalid login state".to_string(), - path: None, - }], - }) -} diff --git a/api/src/routes/mod.rs b/api/src/routes/mod.rs deleted file mode 100644 index 2b2c6854b81248512f3f22d25504227b6cec0ee6..0000000000000000000000000000000000000000 --- a/api/src/routes/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod beamin; -pub mod beamout; -pub mod callback; -pub mod select_realm; -pub mod server_list; diff --git a/api/src/routes/select_realm.rs b/api/src/routes/select_realm.rs deleted file mode 100644 index 9492f46f24dabcedc51a3668f11561d8ccca4ded..0000000000000000000000000000000000000000 --- a/api/src/routes/select_realm.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::config::{StarkingdomsApiConfigRealm, CONFIG}; -use crate::error::{APIError, APIErrorsResponse}; -use crate::AppState; -use actix_web::web::Data; -use actix_web::{get, HttpResponse}; -use log::error; -use serde::Serialize; -use std::collections::HashMap; -use tera::Context; - -#[derive(Serialize)] -pub struct RealmsListTemplateContext { - pub realms: HashMap, - pub back_to: String, -} - -#[get("/select-realm")] -pub async fn select_realm(state: Data) -> HttpResponse { - let context = match Context::from_serialize(RealmsListTemplateContext { - back_to: format!("{}/callback", CONFIG.base), - realms: CONFIG.realms.clone(), - }) { - Ok(r) => r, - Err(e) => { - error!("[context] error creating render context: {}", e); - return HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_INTERNAL_SERVER_ERROR".to_string(), - message: "There was an error processing your request. Please try again later." - .to_string(), - path: None, - }], - }); - } - }; - match state.templates.render("select_realm.tera", &context) { - Ok(r) => HttpResponse::Ok().content_type("text/html").body(r), - Err(e) => { - error!("[context] error creating render context: {}", e); - HttpResponse::InternalServerError().json(APIErrorsResponse { - errors: vec![APIError { - code: "ERR_INTERNAL_SERVER_ERROR".to_string(), - message: "There was an error processing your request. Please try again later." - .to_string(), - path: None, - }], - }) - } - } -} diff --git a/api/src/routes/server_list.rs b/api/src/routes/server_list.rs deleted file mode 100644 index 60f4755c38fc2258c9d2a8b6cb396ebbad4c571c..0000000000000000000000000000000000000000 --- a/api/src/routes/server_list.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::config::CONFIG; -use actix_web::get; -use actix_web::web::Json; -use serde::Serialize; - -#[derive(Serialize)] -pub struct ServerListResponse { - pub servers: Vec, -} - -#[get("server-list")] -pub async fn server_list() -> Json { - Json(ServerListResponse { - servers: CONFIG.servers.clone(), - }) -} diff --git a/api/starkingdoms_api_entities/Cargo.toml b/api/starkingdoms_api_entities/Cargo.toml deleted file mode 100644 index e4cddcdfd41f5343fda00e2b261851f6470fb4ed..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "starkingdoms_api_entities" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -sea-orm = { version = "^0" } diff --git a/api/starkingdoms_api_entities/src/entity/mod.rs b/api/starkingdoms_api_entities/src/entity/mod.rs deleted file mode 100644 index 396669ece549665ecd396a76f96848376dd060e1..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/src/entity/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 - -pub mod prelude; - -pub mod user; -pub mod user_auth_realm; -pub mod user_savefile; diff --git a/api/starkingdoms_api_entities/src/entity/prelude.rs b/api/starkingdoms_api_entities/src/entity/prelude.rs deleted file mode 100644 index 26cd28ab07655687eb68f8922b0e39dfb22742ff..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/src/entity/prelude.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 - -pub use super::user::Entity as User; -pub use super::user_auth_realm::Entity as UserAuthRealm; -pub use super::user_savefile::Entity as UserSavefile; diff --git a/api/starkingdoms_api_entities/src/entity/user.rs b/api/starkingdoms_api_entities/src/entity/user.rs deleted file mode 100644 index d93e232233f9fdab3450ee7ed922c8fda9a46dbd..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/src/entity/user.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "user")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: String, - #[sea_orm(unique)] - pub username: String, - pub created_on: i64, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm(has_many = "super::user_auth_realm::Entity")] - UserAuthRealm, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserAuthRealm.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/api/starkingdoms_api_entities/src/entity/user_auth_realm.rs b/api/starkingdoms_api_entities/src/entity/user_auth_realm.rs deleted file mode 100644 index 510226438bf0390ea248f2cbca00f93ad1d2852d..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/src/entity/user_auth_realm.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "user_auth_realm")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: String, - pub realm: String, - pub realm_native_id: String, - pub user: String, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::user::Entity", - from = "Column::User", - to = "super::user::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - User, - #[sea_orm(has_many = "super::user_savefile::Entity")] - UserSavefile, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::User.def() - } -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserSavefile.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/api/starkingdoms_api_entities/src/entity/user_savefile.rs b/api/starkingdoms_api_entities/src/entity/user_savefile.rs deleted file mode 100644 index 6c8e4fbf113450477a7690027eb98663ec57183f..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/src/entity/user_savefile.rs +++ /dev/null @@ -1,34 +0,0 @@ -//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.2 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "user_savefile")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: String, - pub user: String, - pub data: String, - #[sea_orm(unique)] - pub timestamp: i64, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation { - #[sea_orm( - belongs_to = "super::user_auth_realm::Entity", - from = "Column::User", - to = "super::user_auth_realm::Column::Id", - on_update = "NoAction", - on_delete = "NoAction" - )] - UserAuthRealm, -} - -impl Related for Entity { - fn to() -> RelationDef { - Relation::UserAuthRealm.def() - } -} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/api/starkingdoms_api_entities/src/lib.rs b/api/starkingdoms_api_entities/src/lib.rs deleted file mode 100644 index e8c3d6a4c6dd76d0209422b1a8b1b5a09575d5b5..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_entities/src/lib.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod entity; diff --git a/api/starkingdoms_api_migration/.env b/api/starkingdoms_api_migration/.env deleted file mode 100644 index 49cc7e29bde8d445bf0cdafc992c07a1c0790f2f..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/.env +++ /dev/null @@ -1 +0,0 @@ -DATABASE_URL=postgres://postgres@localhost/starkingdoms \ No newline at end of file diff --git a/api/starkingdoms_api_migration/Cargo.toml b/api/starkingdoms_api_migration/Cargo.toml deleted file mode 100644 index 4875419d0cf044e884b92f05253f7f31f95f13c5..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "starkingdoms_api_migration" -version = "0.1.0" -edition = "2021" -publish = false - -[lib] -name = "starkingdoms_api_migration" -path = "src/lib.rs" - -[dependencies] -async-std = { version = "1", features = ["attributes", "tokio1"] } - -[dependencies.sea-orm-migration] -version = "0.11.0" -features = [ - # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. - # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. - # e.g. - # "runtime-tokio-rustls", # `ASYNC_RUNTIME` feature - # "sqlx-postgres", # `DATABASE_DRIVER` feature - "runtime-tokio-rustls", - "sqlx-postgres" -] diff --git a/api/starkingdoms_api_migration/README.md b/api/starkingdoms_api_migration/README.md deleted file mode 100644 index b3ea53eb4436038446ff10b477366381ab42530c..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Running Migrator CLI - -- Generate a new migration file - ```sh - cargo run -- migrate generate MIGRATION_NAME - ``` -- Apply all pending migrations - ```sh - cargo run - ``` - ```sh - cargo run -- up - ``` -- Apply first 10 pending migrations - ```sh - cargo run -- up -n 10 - ``` -- Rollback last applied migrations - ```sh - cargo run -- down - ``` -- Rollback last 10 applied migrations - ```sh - cargo run -- down -n 10 - ``` -- Drop all tables from the database, then reapply all migrations - ```sh - cargo run -- fresh - ``` -- Rollback all applied migrations, then reapply all migrations - ```sh - cargo run -- refresh - ``` -- Rollback all applied migrations - ```sh - cargo run -- reset - ``` -- Check the status of all migrations - ```sh - cargo run -- status - ``` diff --git a/api/starkingdoms_api_migration/src/lib.rs b/api/starkingdoms_api_migration/src/lib.rs deleted file mode 100644 index 32c20b6e4c0d81f682f179eaf6a5b3c54f1dbde0..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/src/lib.rs +++ /dev/null @@ -1,18 +0,0 @@ -pub use sea_orm_migration::prelude::*; - -pub mod m20230417_162824_create_table_users; -pub mod m20230417_164240_create_table_user_auth_realms; -pub mod m20230420_144333_create_table_user_data; - -pub struct Migrator; - -#[async_trait::async_trait] -impl MigratorTrait for Migrator { - fn migrations() -> Vec> { - vec![ - Box::new(m20230417_162824_create_table_users::Migration), - Box::new(m20230417_164240_create_table_user_auth_realms::Migration), - Box::new(m20230420_144333_create_table_user_data::Migration), - ] - } -} diff --git a/api/starkingdoms_api_migration/src/m20230417_162824_create_table_users.rs b/api/starkingdoms_api_migration/src/m20230417_162824_create_table_users.rs deleted file mode 100644 index b59a6c526ab2c50b1be421f105aa1b9da3bfd307..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/src/m20230417_162824_create_table_users.rs +++ /dev/null @@ -1,40 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(User::Table) - .col(ColumnDef::new(User::Id).string().primary_key().not_null()) - .col( - ColumnDef::new(User::Username) - .string() - .unique_key() - .not_null(), - ) - .col(ColumnDef::new(User::CreatedOn).big_unsigned().not_null()) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(User::Table).to_owned()) - .await - } -} - -/// Learn more at https://docs.rs/sea-query#iden -#[derive(Iden)] -pub enum User { - Table, - Id, - Username, - CreatedOn, -} diff --git a/api/starkingdoms_api_migration/src/m20230417_164240_create_table_user_auth_realms.rs b/api/starkingdoms_api_migration/src/m20230417_164240_create_table_user_auth_realms.rs deleted file mode 100644 index 97cc35488b66ceddf2fce555ca4427ffb210abb8..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/src/m20230417_164240_create_table_user_auth_realms.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::m20230417_162824_create_table_users::User; -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(UserAuthRealm::Table) - .col( - ColumnDef::new(UserAuthRealm::Id) - .string() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(UserAuthRealm::Realm).string().not_null()) - .col( - ColumnDef::new(UserAuthRealm::RealmNativeId) - .string() - .not_null(), - ) - .col(ColumnDef::new(UserAuthRealm::User).string().not_null()) - .foreign_key( - ForeignKey::create() - .from(UserAuthRealm::Table, UserAuthRealm::User) - .to(User::Table, User::Id), - ) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(UserAuthRealm::Table).to_owned()) - .await - } -} - -/// Learn more at https://docs.rs/sea-query#iden -#[derive(Iden)] -pub enum UserAuthRealm { - Table, - Id, - Realm, - RealmNativeId, - User, -} diff --git a/api/starkingdoms_api_migration/src/m20230420_144333_create_table_user_data.rs b/api/starkingdoms_api_migration/src/m20230420_144333_create_table_user_data.rs deleted file mode 100644 index c7e6f7bc4870f0e49f1c8d5f277237e54dadf1a1..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/src/m20230420_144333_create_table_user_data.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::m20230417_164240_create_table_user_auth_realms::UserAuthRealm; -use sea_orm_migration::prelude::*; - -#[derive(DeriveMigrationName)] -pub struct Migration; - -#[async_trait::async_trait] -impl MigrationTrait for Migration { - async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .create_table( - Table::create() - .table(UserSavefile::Table) - .col( - ColumnDef::new(UserSavefile::Id) - .string() - .not_null() - .primary_key(), - ) - .col(ColumnDef::new(UserSavefile::User).string().not_null()) - .col(ColumnDef::new(UserSavefile::Data).string().not_null()) - .col( - ColumnDef::new(UserSavefile::Timestamp) - .big_unsigned() - .not_null() - .unique_key(), - ) - .foreign_key( - ForeignKey::create() - .from(UserSavefile::Table, UserSavefile::User) - .to(UserAuthRealm::Table, UserAuthRealm::Id), - ) - .to_owned(), - ) - .await - } - - async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { - manager - .drop_table(Table::drop().table(UserSavefile::Table).to_owned()) - .await - } -} - -/// Learn more at https://docs.rs/sea-query#iden -#[derive(Iden)] -pub enum UserSavefile { - Table, - Id, - User, - Data, - Timestamp, -} diff --git a/api/starkingdoms_api_migration/src/main.rs b/api/starkingdoms_api_migration/src/main.rs deleted file mode 100644 index 61b3e568e3b3a28d9720f41ad1b07d2bc09d201f..0000000000000000000000000000000000000000 --- a/api/starkingdoms_api_migration/src/main.rs +++ /dev/null @@ -1,6 +0,0 @@ -use sea_orm_migration::prelude::*; - -#[async_std::main] -async fn main() { - cli::run_cli(starkingdoms_api_migration::Migrator).await; -} diff --git a/api/static/all.css b/api/static/all.css deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/api/templates/base.tera b/api/templates/base.tera deleted file mode 100644 index f32a95922bb46cb71fbeeaf9ec7e168640690c5d..0000000000000000000000000000000000000000 --- a/api/templates/base.tera +++ /dev/null @@ -1,14 +0,0 @@ - - - - {% block head %} - {% block title %}StarKingdoms API{% endblock title %} - - {% endblock head %} - - - {% block body %} -

This page has no content.

- {% endblock body %} - - \ No newline at end of file diff --git a/api/templates/select_realm.tera b/api/templates/select_realm.tera deleted file mode 100644 index c534cc1be99ea652500aa13a505beb33017dac79..0000000000000000000000000000000000000000 --- a/api/templates/select_realm.tera +++ /dev/null @@ -1,11 +0,0 @@ -{% extends "base.tera" %} - -{% block title %}Select Auth Provider{% endblock title %} - -{% block body %} -

Select Authentication Provider

- {% for realm_id, realm in realms %} - {{ realm_id }} - {% endfor %} -

Selecting an authentication provider will redirect you to our parent e3team's website for login. You will be returned to StarKingdoms when finished.

-{% endblock body %} \ No newline at end of file