From 74bca308d135646f9189813f7dd125b8ea40fbf2 Mon Sep 17 00:00:00 2001 From: subcrip Date: Sat, 13 Apr 2024 16:40:03 +0800 Subject: [PATCH] feat(server): server features --- Cargo.lock | 45 +++++++++++++++++++ Cargo.toml | 2 + src/constants.rs | 11 +++++ src/db.rs | 41 +++++++++-------- src/main.rs | 33 ++++++++++---- src/server/api.rs | 3 ++ src/server/mod.rs | 4 ++ src/server/server.rs | 14 ++++++ src/{oauth_types => types}/mod.rs | 0 src/{oauth_types => types}/oauth_access.rs | 2 +- .../oauth_application.rs | 0 src/{oauth_types => types}/oauth_resource.rs | 0 src/{oauth_types => types}/oauth_scope.rs | 0 src/{oauth_types => types}/oauth_user.rs | 0 14 files changed, 124 insertions(+), 31 deletions(-) create mode 100644 src/constants.rs create mode 100644 src/server/api.rs create mode 100644 src/server/mod.rs create mode 100644 src/server/server.rs rename src/{oauth_types => types}/mod.rs (100%) rename src/{oauth_types => types}/oauth_access.rs (97%) rename src/{oauth_types => types}/oauth_application.rs (100%) rename src/{oauth_types => types}/oauth_resource.rs (100%) rename src/{oauth_types => types}/oauth_scope.rs (100%) rename src/{oauth_types => types}/oauth_user.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index dc7cb4d..72203a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,6 +138,15 @@ dependencies = [ "pin-project-lite 0.2.13", ] +[[package]] +name = "async-ctrlc" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907279f6e91a51c8ec7cac24711e8308f21da7c10c7700ca2f7e125694ed2df1" +dependencies = [ + "ctrlc", +] + [[package]] name = "async-dup" version = "1.2.4" @@ -525,6 +534,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" version = "0.4.37" @@ -683,6 +698,16 @@ dependencies = [ "cipher", ] +[[package]] +name = "ctrlc" +version = "3.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +dependencies = [ + "nix", + "windows-sys 0.52.0", +] + [[package]] name = "digest" version = "0.9.0" @@ -1205,6 +1230,12 @@ dependencies = [ "log", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.153" @@ -1283,9 +1314,11 @@ dependencies = [ name = "myoauth" version = "0.1.0" dependencies = [ + "async-ctrlc", "async-std", "crypto-hash", "futures", + "lazy_static", "rand 0.8.5", "serde", "serde_json", @@ -1295,6 +1328,18 @@ dependencies = [ "uuid", ] +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.5.0", + "cfg-if 1.0.0", + "cfg_aliases", + "libc", +] + [[package]] name = "num-traits" version = "0.2.18" diff --git a/Cargo.toml b/Cargo.toml index 16aa525..f038368 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,5 @@ futures = "0.3.30" uuid = { version = "1.0.0", features = ["v4", "fast-rng", "macro-diagnostics"] } rand = "0.8.5" crypto-hash = "0.3.4" +lazy_static = "1.4.0" +async-ctrlc = "1.2.0" diff --git a/src/constants.rs b/src/constants.rs new file mode 100644 index 0000000..354d968 --- /dev/null +++ b/src/constants.rs @@ -0,0 +1,11 @@ +use std::env; +use lazy_static::lazy_static; + +lazy_static! { + pub static ref POSTGRES_HOST: String = env::var("POSTGRES_HOST").unwrap_or("127.0.0.1".into()); + pub static ref POSTGRES_PORT: String = env::var("POSTGRES_PORT").unwrap_or("5432".into()); + pub static ref POSTGRES_USER: String = env::var("POSTGRES_USER").unwrap_or("postgres".into()); + pub static ref POSTGRES_PASSWORD: String = env::var("POSTGRES_PASSWORD").unwrap(); + pub static ref HOST: String = env::var("HOST").unwrap_or("127.0.0.1".into()); + pub static ref PORT: String = env::var("PORT").unwrap_or("9929".into()); +} diff --git a/src/db.rs b/src/db.rs index a2194c4..aa8ae60 100644 --- a/src/db.rs +++ b/src/db.rs @@ -54,71 +54,70 @@ impl OAuthDatabase { /// Register an application. /// Applicant: client - pub async fn trusted_register_application(&mut self, name: &String, description: &String) -> Result { + pub async fn trusted_register_application(&mut self, name: &String, description: &String) -> Result { // TEST: functionality - let app = crate::oauth_types::oauth_application::OAuthApplication::create(name, description); - let app_hash = crate::oauth_types::oauth_application::OAuthHashedApplication::from(&app); + let app = crate::types::oauth_application::OAuthApplication::create(name, description); + let app_hash = crate::types::oauth_application::OAuthHashedApplication::from(&app); self.psql_execute("insert into Applications (client_id, client_secret, client_name, client_desc) values ($1, $2, $3, $4)", &[&app_hash.client_id, &app_hash.client_secret, &app_hash.client_name, &app_hash.client_desc]).await?; Ok(app) } /// Register a resource. /// Applicant: resource - pub async fn trusted_register_resource(&mut self, name: &String, description: &String) -> Result { + pub async fn trusted_register_resource(&mut self, name: &String, description: &String) -> Result { // TEST: functionality - let resource = crate::oauth_types::oauth_resource::OAuthResource::create(name, description); + let resource = crate::types::oauth_resource::OAuthResource::create(name, description); self.psql_execute("insert into Resources (resource_id, resource_name, resource_desc) values ($1, $2, $3)", &[&resource.resource_id, &resource.resource_name, &resource.resource_desc]).await?; Ok(resource) } /// Register a scope. /// Applicant: resource - pub async fn trusted_register_scope(&mut self, resource_id: &Uuid, name: &String, description: &String) -> Result { + pub async fn trusted_register_scope(&mut self, resource_id: &Uuid, name: &String, description: &String) -> Result { // TEST: functionality - let scope = crate::oauth_types::oauth_scope::OAuthScope::create(resource_id, name, description); + let scope = crate::types::oauth_scope::OAuthScope::create(resource_id, name, description); self.psql_execute("insert into Scopes (scope_id, resource_id, scope_desc) values ($1, $2, $3)", &[&scope.scope_id, &scope.resource_id, &scope.scope_desc]).await?; Ok(scope) } /// Register an access relation. /// Applicant: client - pub async fn trusted_register_access(&mut self, app: &crate::oauth_types::oauth_application::OAuthHashedApplication, scope: &crate::oauth_types::oauth_scope::OAuthScope) -> Result<(), tokio_postgres::Error> { - let access = crate::oauth_types::oauth_access::OAuthApplicationAccess::create(app, scope); + pub async fn trusted_register_access(&mut self, app: &crate::types::oauth_application::OAuthHashedApplication, scope: &crate::types::oauth_scope::OAuthScope) -> Result<(), tokio_postgres::Error> { + let access = crate::types::oauth_access::OAuthApplicationAccess::create(app, scope); self.psql_execute("insert into ApplicationAccess(access_id, client_id, scope_id) values ($1, $2, $3)", &[&access.access_id, &access.client_id, &access.scope_id]).await?; Ok(()) } /// Register a user. /// Applicant: resource - pub async fn trusted_register_user(&mut self, name: &String) -> Result { - let user = crate::oauth_types::oauth_user::OAuthUser::create(name); + pub async fn trusted_register_user(&mut self, name: &String) -> Result { + let user = crate::types::oauth_user::OAuthUser::create(name); self.psql_execute("insert into Users(user_id, user_name) values ($1, $2)", &[&user.user_id, &user.user_name]).await?; Ok(user) } /// Issue a master token. /// Applicant: master - pub async fn trusted_issue_master_db_token(&mut self, description: &String) -> Result { + pub async fn trusted_issue_master_db_token(&mut self, description: &String) -> Result { // TEST: functionality - let access = crate::oauth_types::oauth_access::OAuthMasterDBAccess::create(description); - let hashed = crate::oauth_types::oauth_access::OAuthHashedMasterDBAccess::from(&access); + let access = crate::types::oauth_access::OAuthMasterDBAccess::create(description); + let hashed = crate::types::oauth_access::OAuthHashedMasterDBAccess::from(&access); self.psql_execute("insert into MasterDBAccess(master_db_id, master_db_token, master_db_desc) values ($1, $2, $3)", &[&hashed.master_db_id, &hashed.master_db_token, &hashed.master_db_desc]).await?; Ok(access) } - // TODO: other type of db tokens - pub async fn trusted_issue_resource_db_token(&mut self, resource_id: &Uuid, description: &String) -> Result { + pub async fn trusted_issue_resource_db_token(&mut self, resource_id: &Uuid, description: &String) -> Result { // TEST: functionality - let access = crate::oauth_types::oauth_access::OAuthResourceDBAccess::create(resource_id, description); - let hashed = crate::oauth_types::oauth_access::OAuthHashedResourceDBAccess::from(&access); + let access = crate::types::oauth_access::OAuthResourceDBAccess::create(resource_id, description); + let hashed = crate::types::oauth_access::OAuthHashedResourceDBAccess::from(&access); self.psql_execute("insert into ResourceDBAccess(resource_db_id, resource_id, resource_db_token, resource_db_desc) values ($1, $2, $3, $4)", &[&hashed.resource_db_id, &hashed.resource_id, &hashed.resource_db_token, &hashed.resource_db_desc]).await?; Ok(access) } - pub async fn trusted_issue_client_db_token(&mut self, client_id: &Uuid, description: &String) -> Result { + pub async fn trusted_issue_client_db_token(&mut self, client_id: &Uuid, description: &String) -> Result { // TEST: functionality - let access = crate::oauth_types::oauth_access::OAuthClientDBAccess::create(client_id, description); - let hashed = crate::oauth_types::oauth_access::OAuthHashedClientDBAccess::from(&access); + let access = crate::types::oauth_access::OAuthClientDBAccess::create(client_id, description); + let hashed = crate::types::oauth_access::OAuthHashedClientDBAccess::from(&access); self.psql_execute("insert into ClientDBAccess(client_db_id, client_id, client_db_token, client_db_desc)", &[&hashed.client_db_id, &hashed.client_id, &hashed.client_db_token, &hashed.client_db_desc]).await?; Ok(access) } diff --git a/src/main.rs b/src/main.rs index c847124..e9e2ec5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,39 @@ +use async_std::prelude::FutureExt; use tide::Request; use tide::prelude::*; +mod server; mod db; -mod oauth_types; +mod types; mod misc; +mod constants; #[tokio::main] async fn main() { - let postgres_host = std::env::var("POSTGRES_HOST").unwrap_or(String::from("localhost")); - let postgres_port = std::env::var("POSTGRES_PORT").unwrap_or(String::from("5432")); - let postgres_user = std::env::var("POSTGRES_USER").unwrap_or(String::from("postgres")); - let postgres_password = std::env::var("POSTGRES_PASSWORD").unwrap(); + tide::log::start(); loop { - if let Ok(mut b) = db::OAuthDatabase::connect(postgres_host.as_str(), str::parse(postgres_port.as_str()).unwrap(), postgres_user.as_str(), postgres_password.as_str(), "myoauth").await { - b.init().await.unwrap(); + if let Ok(mut b) = db::OAuthDatabase::connect(constants::POSTGRES_HOST.as_str(), str::parse(constants::POSTGRES_PORT.as_str()).unwrap(), constants::POSTGRES_USER.as_str(), constants::POSTGRES_PASSWORD.as_str(), "myoauth").await { + match b.init().await { + Ok(()) => tide::log::info!("Finished initializing."), + Err(e) => tide::log::warn!("{}", e), + } break; } + tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await; + } + let serve = async { + match server::OAuthServer::serve(&format!("{}:{}", constants::HOST.as_str(), constants::PORT.as_str()).into()).await { + Ok(_) => (), + Err(e) => tide::log::error!("{}", e), + } + }; + match async_ctrlc::CtrlC::new() { + Ok(ctrlc) => { + ctrlc.race(serve).await; + tide::log::info!("Server stopped."); + }, + Err(e) => tide::log::error!("{}", e) } - // let u = b.trusted_register_user().await.unwrap(); - // println!("Successfully registered user with uid = {}", u.user_id); } #[tokio::test] diff --git a/src/server/api.rs b/src/server/api.rs new file mode 100644 index 0000000..edd41b4 --- /dev/null +++ b/src/server/api.rs @@ -0,0 +1,3 @@ +pub async fn hello(req: tide::Request<()>) -> tide::Result { + Ok("Hello".into()) +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..eb7e2ed --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,4 @@ +mod server; +mod api; + +pub use server::OAuthServer; diff --git a/src/server/server.rs b/src/server/server.rs new file mode 100644 index 0000000..a87e0c7 --- /dev/null +++ b/src/server/server.rs @@ -0,0 +1,14 @@ +use tide::Request; +use tide::prelude::*; + +use super::api; + +pub struct OAuthServer; + +impl OAuthServer { + pub async fn serve(bind_addr: &String) -> async_std::io::Result<()> { + let mut server = tide::new(); + server.at("/hello").get(api::hello); + server.listen(bind_addr).await + } +} diff --git a/src/oauth_types/mod.rs b/src/types/mod.rs similarity index 100% rename from src/oauth_types/mod.rs rename to src/types/mod.rs diff --git a/src/oauth_types/oauth_access.rs b/src/types/oauth_access.rs similarity index 97% rename from src/oauth_types/oauth_access.rs rename to src/types/oauth_access.rs index 481df9c..ab6b02f 100644 --- a/src/oauth_types/oauth_access.rs +++ b/src/types/oauth_access.rs @@ -7,7 +7,7 @@ pub struct OAuthApplicationAccess { } impl OAuthApplicationAccess { - pub fn create(app: &crate::oauth_types::oauth_application::OAuthHashedApplication, scope: &crate::oauth_types::oauth_scope::OAuthScope) -> Self { + pub fn create(app: &crate::types::oauth_application::OAuthHashedApplication, scope: &crate::types::oauth_scope::OAuthScope) -> Self { Self { access_id: Uuid::new_v4(), client_id: app.client_id, diff --git a/src/oauth_types/oauth_application.rs b/src/types/oauth_application.rs similarity index 100% rename from src/oauth_types/oauth_application.rs rename to src/types/oauth_application.rs diff --git a/src/oauth_types/oauth_resource.rs b/src/types/oauth_resource.rs similarity index 100% rename from src/oauth_types/oauth_resource.rs rename to src/types/oauth_resource.rs diff --git a/src/oauth_types/oauth_scope.rs b/src/types/oauth_scope.rs similarity index 100% rename from src/oauth_types/oauth_scope.rs rename to src/types/oauth_scope.rs diff --git a/src/oauth_types/oauth_user.rs b/src/types/oauth_user.rs similarity index 100% rename from src/oauth_types/oauth_user.rs rename to src/types/oauth_user.rs