feat(server): server features
Build Docker Image / build-nightly (push) Successful in 2m26s Details

This commit is contained in:
subcrip 2024-04-13 16:40:03 +08:00
parent 96619e7c43
commit 74bca308d1
Signed by: subcrip
SSH Key Fingerprint: SHA256:dFPFi68d8C87YkFkEBU4TkcrYRySWpekRR1hbnDWUCw
14 changed files with 124 additions and 31 deletions

45
Cargo.lock generated
View File

@ -138,6 +138,15 @@ dependencies = [
"pin-project-lite 0.2.13", "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]] [[package]]
name = "async-dup" name = "async-dup"
version = "1.2.4" version = "1.2.4"
@ -525,6 +534,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.37" version = "0.4.37"
@ -683,6 +698,16 @@ dependencies = [
"cipher", "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]] [[package]]
name = "digest" name = "digest"
version = "0.9.0" version = "0.9.0"
@ -1205,6 +1230,12 @@ dependencies = [
"log", "log",
] ]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.153" version = "0.2.153"
@ -1283,9 +1314,11 @@ dependencies = [
name = "myoauth" name = "myoauth"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-ctrlc",
"async-std", "async-std",
"crypto-hash", "crypto-hash",
"futures", "futures",
"lazy_static",
"rand 0.8.5", "rand 0.8.5",
"serde", "serde",
"serde_json", "serde_json",
@ -1295,6 +1328,18 @@ dependencies = [
"uuid", "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]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.18" version = "0.2.18"

View File

@ -16,3 +16,5 @@ futures = "0.3.30"
uuid = { version = "1.0.0", features = ["v4", "fast-rng", "macro-diagnostics"] } uuid = { version = "1.0.0", features = ["v4", "fast-rng", "macro-diagnostics"] }
rand = "0.8.5" rand = "0.8.5"
crypto-hash = "0.3.4" crypto-hash = "0.3.4"
lazy_static = "1.4.0"
async-ctrlc = "1.2.0"

11
src/constants.rs Normal file
View File

@ -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());
}

View File

@ -54,71 +54,70 @@ impl OAuthDatabase {
/// Register an application. /// Register an application.
/// Applicant: client /// Applicant: client
pub async fn trusted_register_application(&mut self, name: &String, description: &String) -> Result<crate::oauth_types::oauth_application::OAuthApplication, tokio_postgres::Error> { pub async fn trusted_register_application(&mut self, name: &String, description: &String) -> Result<crate::types::oauth_application::OAuthApplication, tokio_postgres::Error> {
// TEST: functionality // TEST: functionality
let app = crate::oauth_types::oauth_application::OAuthApplication::create(name, description); let app = crate::types::oauth_application::OAuthApplication::create(name, description);
let app_hash = crate::oauth_types::oauth_application::OAuthHashedApplication::from(&app); 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?; 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) Ok(app)
} }
/// Register a resource. /// Register a resource.
/// Applicant: resource /// Applicant: resource
pub async fn trusted_register_resource(&mut self, name: &String, description: &String) -> Result<crate::oauth_types::oauth_resource::OAuthResource, tokio_postgres::Error> { pub async fn trusted_register_resource(&mut self, name: &String, description: &String) -> Result<crate::types::oauth_resource::OAuthResource, tokio_postgres::Error> {
// TEST: functionality // 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?; 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) Ok(resource)
} }
/// Register a scope. /// Register a scope.
/// Applicant: resource /// Applicant: resource
pub async fn trusted_register_scope(&mut self, resource_id: &Uuid, name: &String, description: &String) -> Result<crate::oauth_types::oauth_scope::OAuthScope, tokio_postgres::Error> { pub async fn trusted_register_scope(&mut self, resource_id: &Uuid, name: &String, description: &String) -> Result<crate::types::oauth_scope::OAuthScope, tokio_postgres::Error> {
// TEST: functionality // 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?; 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) Ok(scope)
} }
/// Register an access relation. /// Register an access relation.
/// Applicant: client /// 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> { 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::oauth_types::oauth_access::OAuthApplicationAccess::create(app, scope); 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?; 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(()) Ok(())
} }
/// Register a user. /// Register a user.
/// Applicant: resource /// Applicant: resource
pub async fn trusted_register_user(&mut self, name: &String) -> Result<crate::oauth_types::oauth_user::OAuthUser, tokio_postgres::Error> { pub async fn trusted_register_user(&mut self, name: &String) -> Result<crate::types::oauth_user::OAuthUser, tokio_postgres::Error> {
let user = crate::oauth_types::oauth_user::OAuthUser::create(name); 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?; self.psql_execute("insert into Users(user_id, user_name) values ($1, $2)", &[&user.user_id, &user.user_name]).await?;
Ok(user) Ok(user)
} }
/// Issue a master token. /// Issue a master token.
/// Applicant: master /// Applicant: master
pub async fn trusted_issue_master_db_token(&mut self, description: &String) -> Result<crate::oauth_types::oauth_access::OAuthMasterDBAccess, tokio_postgres::Error> { pub async fn trusted_issue_master_db_token(&mut self, description: &String) -> Result<crate::types::oauth_access::OAuthMasterDBAccess, tokio_postgres::Error> {
// TEST: functionality // TEST: functionality
let access = crate::oauth_types::oauth_access::OAuthMasterDBAccess::create(description); let access = crate::types::oauth_access::OAuthMasterDBAccess::create(description);
let hashed = crate::oauth_types::oauth_access::OAuthHashedMasterDBAccess::from(&access); 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?; 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) Ok(access)
} }
// TODO: other type of db tokens pub async fn trusted_issue_resource_db_token(&mut self, resource_id: &Uuid, description: &String) -> Result<crate::types::oauth_access::OAuthResourceDBAccess, tokio_postgres::Error> {
pub async fn trusted_issue_resource_db_token(&mut self, resource_id: &Uuid, description: &String) -> Result<crate::oauth_types::oauth_access::OAuthResourceDBAccess, tokio_postgres::Error> {
// TEST: functionality // TEST: functionality
let access = crate::oauth_types::oauth_access::OAuthResourceDBAccess::create(resource_id, description); let access = crate::types::oauth_access::OAuthResourceDBAccess::create(resource_id, description);
let hashed = crate::oauth_types::oauth_access::OAuthHashedResourceDBAccess::from(&access); 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?; 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) Ok(access)
} }
pub async fn trusted_issue_client_db_token(&mut self, client_id: &Uuid, description: &String) -> Result<crate::oauth_types::oauth_access::OAuthClientDBAccess, tokio_postgres::Error> { pub async fn trusted_issue_client_db_token(&mut self, client_id: &Uuid, description: &String) -> Result<crate::types::oauth_access::OAuthClientDBAccess, tokio_postgres::Error> {
// TEST: functionality // TEST: functionality
let access = crate::oauth_types::oauth_access::OAuthClientDBAccess::create(client_id, description); let access = crate::types::oauth_access::OAuthClientDBAccess::create(client_id, description);
let hashed = crate::oauth_types::oauth_access::OAuthHashedClientDBAccess::from(&access); 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?; 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) Ok(access)
} }

View File

@ -1,24 +1,39 @@
use async_std::prelude::FutureExt;
use tide::Request; use tide::Request;
use tide::prelude::*; use tide::prelude::*;
mod server;
mod db; mod db;
mod oauth_types; mod types;
mod misc; mod misc;
mod constants;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let postgres_host = std::env::var("POSTGRES_HOST").unwrap_or(String::from("localhost")); tide::log::start();
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();
loop { 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 { 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 {
b.init().await.unwrap(); match b.init().await {
Ok(()) => tide::log::info!("Finished initializing."),
Err(e) => tide::log::warn!("{}", e),
}
break; 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] #[tokio::test]

3
src/server/api.rs Normal file
View File

@ -0,0 +1,3 @@
pub async fn hello(req: tide::Request<()>) -> tide::Result {
Ok("Hello".into())
}

4
src/server/mod.rs Normal file
View File

@ -0,0 +1,4 @@
mod server;
mod api;
pub use server::OAuthServer;

14
src/server/server.rs Normal file
View File

@ -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
}
}

View File

@ -7,7 +7,7 @@ pub struct OAuthApplicationAccess {
} }
impl 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 { Self {
access_id: Uuid::new_v4(), access_id: Uuid::new_v4(),
client_id: app.client_id, client_id: app.client_id,