From 9ad93793819755e332cc607475c2f6b6ce704fae Mon Sep 17 00:00:00 2001 From: trivernis Date: Fri, 11 Sep 2020 21:21:22 +0200 Subject: [PATCH] Remove redis dependencies Signed-off-by: trivernis --- Cargo.lock | 398 +------------------------------ Cargo.toml | 1 - src/database/mod.rs | 50 +--- src/database/permissions.rs | 9 +- src/database/redis_operations.rs | 5 - src/database/role_permissions.rs | 9 +- src/database/roles.rs | 14 +- src/database/tokens.rs | 240 ++++++++++++++----- src/database/user_roles.rs | 9 +- src/database/users.rs | 65 +++-- src/server/http_server.rs | 16 +- src/utils/error.rs | 17 +- 12 files changed, 242 insertions(+), 591 deletions(-) delete mode 100644 src/database/redis_operations.rs diff --git a/Cargo.lock b/Cargo.lock index fc58b0c..9e4ce5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,92 +33,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" -[[package]] -name = "async-channel" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21279cfaa4f47df10b1816007e738ca3747ef2ee53ffc51cdbf57a8bb266fee3" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - -[[package]] -name = "async-executor" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f47c78ea98277cb1f5e6f60ba4fc762f5eafe9f6511bc2f7dfd8b75c225650" -dependencies = [ - "async-io", - "futures-lite", - "multitask", - "parking 1.0.6", - "scoped-tls", - "waker-fn", -] - -[[package]] -name = "async-io" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae22a338d28c75b53702b66f77979062cb29675db376d99e451af4fa79dedb3" -dependencies = [ - "cfg-if", - "concurrent-queue", - "futures-lite", - "libc", - "once_cell", - "parking 2.0.0", - "polling", - "socket2", - "vec-arena", - "wepoll-sys-stjepang", - "winapi 0.3.9", -] - -[[package]] -name = "async-mutex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66941c2577c4fa351e4ce5fdde8f86c69b88d623f3b955be1bc7362a23434632" -dependencies = [ - "event-listener", -] - -[[package]] -name = "async-std" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c8da367da62b8ff2313c406c9ac091c1b31d67a165becdd2de380d846260f7" -dependencies = [ - "async-executor", - "async-io", - "async-mutex", - "async-task", - "blocking", - "crossbeam-utils", - "futures-channel", - "futures-core", - "futures-io", - "futures-lite", - "kv-log-macro", - "log 0.4.11", - "memchr", - "num_cpus", - "once_cell", - "pin-project-lite", - "pin-utils", - "slab", - "wasm-bindgen-futures", -] - -[[package]] -name = "async-task" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17772156ef2829aadc587461c7753af20b7e8db1529bc66855add962a3b35d3" - [[package]] name = "async-trait" version = "0.1.40" @@ -130,12 +44,6 @@ dependencies = [ "syn", ] -[[package]] -name = "atomic-waker" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" - [[package]] name = "atty" version = "0.2.14" @@ -222,19 +130,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "blocking" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5800d29218fea137b0880387e5948694a23c93fcdde157006966693a865c7c" -dependencies = [ - "async-channel", - "atomic-waker", - "futures-lite", - "once_cell", - "waker-fn", -] - [[package]] name = "blowfish" version = "0.6.0" @@ -282,12 +177,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -[[package]] -name = "bumpalo" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" - [[package]] name = "byteorder" version = "1.3.4" @@ -300,12 +189,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" -[[package]] -name = "cache-padded" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" - [[package]] name = "cc" version = "1.0.59" @@ -364,28 +247,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "combine" -version = "4.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2809f67365382d65fd2b6d9c22577231b954ed27400efeafbe687bda75abcc0b" -dependencies = [ - "bytes", - "futures-util", - "memchr", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "concurrent-queue" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" -dependencies = [ - "cache-padded", -] - [[package]] name = "constant_time_eq" version = "0.1.5" @@ -474,12 +335,6 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" -[[package]] -name = "dtoa" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" - [[package]] name = "env_logger" version = "0.7.1" @@ -493,24 +348,12 @@ dependencies = [ "termcolor", ] -[[package]] -name = "event-listener" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cd41440ae7e4734bbd42302f63eaba892afc93a3912dad84006247f0dedb0e" - [[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" -[[package]] -name = "fastrand" -version = "1.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c85295147490b8fcf2ea3d104080a105a8b2c63f9c319e82c02d8e952388919" - [[package]] name = "filetime" version = "0.2.12" @@ -539,7 +382,6 @@ dependencies = [ "msgrpc", "postgres", "rand 0.7.3", - "redis", "rmp", "rmp-serde", "rouille", @@ -549,12 +391,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "fuchsia-cprng" version = "0.1.1" @@ -625,21 +461,6 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" -[[package]] -name = "futures-lite" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97999970129b808f0ccba93211201d431fcc12d7e1ffae03a61b5cedd1a7ced2" -dependencies = [ - "fastrand", - "futures-core", - "futures-io", - "memchr", - "parking 2.0.0", - "pin-project-lite", - "waker-fn", -] - [[package]] name = "futures-macro" version = "0.3.5" @@ -762,17 +583,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "idna" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "instant" version = "0.1.6" @@ -794,15 +604,6 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" -[[package]] -name = "js-sys" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" -dependencies = [ - "wasm-bindgen", -] - [[package]] name = "kernel32-sys" version = "0.2.2" @@ -813,15 +614,6 @@ dependencies = [ "winapi-build", ] -[[package]] -name = "kv-log-macro" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" -dependencies = [ - "log 0.4.11", -] - [[package]] name = "lazy_static" version = "1.4.0" @@ -979,17 +771,6 @@ dependencies = [ "twoway", ] -[[package]] -name = "multitask" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c09c35271e7dcdb5f709779111f2c8e8ab8e06c1b587c1c6a9e179d865aaa5b4" -dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", -] - [[package]] name = "net2" version = "0.2.35" @@ -1042,18 +823,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "parking" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb300f271742d4a2a66c01b6b2fa0c83dfebd2e0bf11addb879a3547b4ed87c" - -[[package]] -name = "parking" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" - [[package]] name = "parking_lot" version = "0.11.0" @@ -1181,19 +950,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "polling" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fffa183f6bd5f1a8a3e1f60ce2f8d5621e350eed84a62d6daaa5b9d1aaf6fbd" -dependencies = [ - "cfg-if", - "libc", - "log 0.4.11", - "wepoll-sys-stjepang", - "winapi 0.3.9", -] - [[package]] name = "postgres" version = "0.17.5" @@ -1461,27 +1217,6 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "redis" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95357caf2640abc54651b93c98a8df4fe1ccbf44b8e601ccdf43d5c1451f29ac" -dependencies = [ - "async-std", - "async-trait", - "bytes", - "combine", - "dtoa", - "futures-util", - "itoa", - "percent-encoding 2.1.0", - "pin-project-lite", - "sha1", - "tokio", - "tokio-util", - "url 2.1.1", -] - [[package]] name = "redox_syscall" version = "0.1.57" @@ -1569,7 +1304,7 @@ dependencies = [ "threadpool", "time", "tiny_http", - "url 1.7.2", + "url", ] [[package]] @@ -1596,12 +1331,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - [[package]] name = "scopeguard" version = "1.1.0" @@ -1692,18 +1421,6 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" -[[package]] -name = "socket2" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "winapi 0.3.9", -] - [[package]] name = "stringprep" version = "0.1.2" @@ -1812,7 +1529,7 @@ dependencies = [ "chrono", "chunked_transfer", "log 0.4.11", - "url 1.7.2", + "url", ] [[package]] @@ -1828,7 +1545,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" dependencies = [ "bytes", - "fnv", "futures-core", "iovec", "lazy_static", @@ -1930,28 +1646,11 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna 0.1.5", + "idna", "matches", "percent-encoding 1.0.1", ] -[[package]] -name = "url" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -dependencies = [ - "idna 0.2.0", - "matches", - "percent-encoding 2.1.0", -] - -[[package]] -name = "vec-arena" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb18268690309760d59ee1a9b21132c126ba384f374c59a94db4bc03adeb561" - [[package]] name = "version_check" version = "0.1.5" @@ -1964,12 +1663,6 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" -[[package]] -name = "waker-fn" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" - [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -1982,91 +1675,6 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" -[[package]] -name = "wasm-bindgen" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" -dependencies = [ - "bumpalo", - "lazy_static", - "log 0.4.11", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7866cab0aa01de1edf8b5d7936938a7e397ee50ce24119aef3e1eaa3b6171da" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" - -[[package]] -name = "web-sys" -version = "0.3.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "wepoll-sys-stjepang" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd319e971980166b53e17b1026812ad66c6b54063be879eb182342b55284694" -dependencies = [ - "cc", -] - [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index a5cf68b..f38596f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ msgrpc = {path = "./msg-rpc"} postgres = "0.17.5" serde_postgres = "0.2.0" dotenv = "0.15.0" -redis = "0.17.0" serde = {version = "1.0.115", features = ["serde_derive"]} rand = "0.7.3" bcrypt = "0.8.2" diff --git a/src/database/mod.rs b/src/database/mod.rs index bbb231b..1cba435 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -3,18 +3,14 @@ use crate::database::role_permissions::RolePermissions; use crate::database::roles::Roles; use crate::database::user_roles::UserRoles; use crate::database::users::Users; -use crate::utils::error::{ - DBError, DatabaseClient, DatabaseResult, PostgresError, RedisClient, RedisConnection, -}; +use crate::utils::error::{DBError, DatabaseClient, DatabaseResult, PostgresError}; use dotenv; use postgres::{Client, NoTls}; -use redis::RedisResult; use std::sync::{Arc, Mutex}; pub mod database_error; pub mod models; pub mod permissions; -pub mod redis_operations; pub mod role_permissions; pub mod roles; pub mod tokens; @@ -23,21 +19,15 @@ pub mod users; const DB_CONNECTION_URL: &str = "POSTGRES_CONNECTION_URL"; const DEFAULT_CONNECTION: &str = "postgres://postgres:postgres@localhost/postgres"; -const REDIS_CONNECTION_URL: &str = "REDIS_CONNECTION_URL"; -const DEFAULT_REDIS_CONNECTION: &str = "redis:://127.0.0.1/"; pub trait Table { - fn new( - database_connection: Arc>, - redis_connection: Arc>, - ) -> Self; + fn new(database_connection: Arc>) -> Self; fn init(&self) -> DatabaseResult<()>; } #[derive(Clone)] pub struct Database { database_connection: Arc>, - redis_connection: Arc>, pub users: Users, pub roles: Roles, pub permissions: Permissions, @@ -50,32 +40,13 @@ impl Database { let database_connection = Arc::new(Mutex::new( get_database_connection().map_err(|e| DBError::Postgres(e))?, )); - let redis_connection = Arc::new(Mutex::new( - get_redis_connection().map_err(|e| DBError::Redis(e))?, - )); Ok(Self { - users: Users::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), - roles: Roles::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), - permissions: Permissions::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), - user_roles: UserRoles::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), - role_permission: RolePermissions::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), + users: Users::new(Arc::clone(&database_connection)), + roles: Roles::new(Arc::clone(&database_connection)), + permissions: Permissions::new(Arc::clone(&database_connection)), + user_roles: UserRoles::new(Arc::clone(&database_connection)), + role_permission: RolePermissions::new(Arc::clone(&database_connection)), database_connection, - redis_connection, }) } @@ -95,10 +66,3 @@ fn get_database_connection() -> Result { let conn_url = dotenv::var(DB_CONNECTION_URL).unwrap_or(DEFAULT_CONNECTION.to_string()); Client::connect(conn_url.as_str(), NoTls) } - -fn get_redis_connection() -> RedisResult { - let conn_url = - dotenv::var(REDIS_CONNECTION_URL).unwrap_or(DEFAULT_REDIS_CONNECTION.to_string()); - let client = RedisClient::open(conn_url)?; - client.get_connection() -} diff --git a/src/database/permissions.rs b/src/database/permissions.rs index f7fc5fb..f7e356b 100644 --- a/src/database/permissions.rs +++ b/src/database/permissions.rs @@ -1,5 +1,5 @@ use crate::database::models::{CreatePermissionsEntry, Permission}; -use crate::database::{DatabaseClient, DatabaseResult, RedisConnection, Table}; +use crate::database::{DatabaseClient, DatabaseResult, Table}; use crate::utils::error::DBError; use postgres::Client; use std::sync::{Arc, Mutex}; @@ -7,17 +7,12 @@ use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct Permissions { database_connection: Arc>, - redis_connection: Arc>, } impl Table for Permissions { - fn new( - database_connection: Arc>, - redis_connection: Arc>, - ) -> Self { + fn new(database_connection: Arc>) -> Self { Self { database_connection, - redis_connection, } } diff --git a/src/database/redis_operations.rs b/src/database/redis_operations.rs deleted file mode 100644 index cd24757..0000000 --- a/src/database/redis_operations.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub const SET: &str = "SET"; -pub const EXPIRE: &str = "EXPIRE"; -pub const TTL: &str = "TTL"; -pub const EX: &str = "EX"; -pub const GET: &str = "GET"; diff --git a/src/database/role_permissions.rs b/src/database/role_permissions.rs index 55fe2db..60f3ec5 100644 --- a/src/database/role_permissions.rs +++ b/src/database/role_permissions.rs @@ -1,22 +1,17 @@ use crate::database::models::Permission; -use crate::database::{DatabaseClient, DatabaseResult, RedisConnection, Table}; +use crate::database::{DatabaseClient, DatabaseResult, Table}; use crate::utils::error::DBError; use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct RolePermissions { database_connection: Arc>, - redis_connection: Arc>, } impl Table for RolePermissions { - fn new( - database_connection: Arc>, - redis_connection: Arc>, - ) -> Self { + fn new(database_connection: Arc>) -> Self { Self { database_connection, - redis_connection, } } diff --git a/src/database/roles.rs b/src/database/roles.rs index e1b33be..05118ab 100644 --- a/src/database/roles.rs +++ b/src/database/roles.rs @@ -1,6 +1,6 @@ use crate::database::models::Role; use crate::database::role_permissions::RolePermissions; -use crate::database::{DatabaseResult, RedisConnection, Table}; +use crate::database::{DatabaseResult, Table}; use crate::utils::error::DBError; use postgres::Client; use std::sync::{Arc, Mutex}; @@ -8,22 +8,14 @@ use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct Roles { database_connection: Arc>, - redis_connection: Arc>, role_permission: RolePermissions, } impl Table for Roles { - fn new( - database_connection: Arc>, - redis_connection: Arc>, - ) -> Self { + fn new(database_connection: Arc>) -> Self { Self { - role_permission: RolePermissions::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), + role_permission: RolePermissions::new(Arc::clone(&database_connection)), database_connection, - redis_connection, } } diff --git a/src/database/tokens.rs b/src/database/tokens.rs index f46b3ed..2c60139 100644 --- a/src/database/tokens.rs +++ b/src/database/tokens.rs @@ -1,13 +1,12 @@ -use crate::database::redis_operations::{EX, GET, SET, TTL}; -use crate::utils::error::RedisConnection; -use crate::utils::{create_user_token, get_user_id_from_token}; -use byteorder::{BigEndian, ByteOrder}; -use redis::{ErrorKind, RedisError, RedisResult}; +use crate::utils::{create_user_token, get_user_id_from_token, TOKEN_LENGTH}; use serde::Serialize; +use std::cmp::{max, min}; +use std::collections::HashMap; +use std::time::Instant; use zeroize::Zeroize; -const REQUEST_TOKEN_EXPIRE_SECONDS: i32 = 60 * 10; -const REFRESH_TOKEN_EXPIRE_SECONDS: i32 = 60 * 60 * 24; +const REQUEST_TOKEN_EXPIRE_SECONDS: u32 = 60 * 10; +const REFRESH_TOKEN_EXPIRE_SECONDS: u32 = 60 * 60 * 24; #[derive(Clone, Debug, Zeroize, Serialize)] #[zeroize(drop)] @@ -23,8 +22,8 @@ impl SessionTokens { Self { request_token: base64::encode(create_user_token(user_id)), refresh_token: base64::encode(create_user_token(user_id)), - request_ttl: REQUEST_TOKEN_EXPIRE_SECONDS, - refresh_ttl: REFRESH_TOKEN_EXPIRE_SECONDS, + request_ttl: REQUEST_TOKEN_EXPIRE_SECONDS as i32, + refresh_ttl: REFRESH_TOKEN_EXPIRE_SECONDS as i32, } } @@ -32,45 +31,19 @@ impl SessionTokens { Self { request_token, refresh_token, - request_ttl: REQUEST_TOKEN_EXPIRE_SECONDS, - refresh_ttl: REFRESH_TOKEN_EXPIRE_SECONDS, + request_ttl: REQUEST_TOKEN_EXPIRE_SECONDS as i32, + refresh_ttl: REFRESH_TOKEN_EXPIRE_SECONDS as i32, } } - pub fn retrieve(user_id: i32, redis_connection: &mut RedisConnection) -> RedisResult { - let redis_request_key = format!("user-{}_request", user_id); - let request_token: String = redis::cmd(GET) - .arg(&redis_request_key) - .query(redis_connection)?; - let redis_refresh_key = format!("user-{}_refresh", user_id); - let refresh_token: String = redis::cmd(GET) - .arg(&redis_refresh_key) - .query(redis_connection)?; - - if request_token.len() == 0 { - return Err(RedisError::from(( - ErrorKind::ResponseError, - "No refresh token available", - ))); - } - if refresh_token.len() == 0 { - return Err(RedisError::from(( - ErrorKind::ResponseError, - "No refresh token available", - ))); - } - let request_ttl: i32 = redis::cmd(TTL) - .arg(&redis_request_key) - .query(redis_connection)?; - let refresh_ttl: i32 = redis::cmd(TTL) - .arg(&redis_refresh_key) - .query(redis_connection)?; - - Ok(Self { - request_token, + pub fn from_entry(other: &TokenStoreEntry) -> Option { + let request_token = other.request_token()?; + let refresh_token = other.refresh_token()?; + Some(Self { refresh_token, - request_ttl, - refresh_ttl, + request_token, + request_ttl: other.request_ttl(), + refresh_ttl: other.refresh_ttl(), }) } @@ -84,26 +57,167 @@ impl SessionTokens { } /// Saves the tokens into the database - pub fn store(&self, redis_connection: &mut RedisConnection) -> RedisResult<()> { - let id = self.get_user_id(); - - let redis_request_key = format!("user-{}_request", id); - redis::cmd(SET) - .arg(&redis_request_key) - .arg(&self.request_token) - .arg(EX) - .arg(REQUEST_TOKEN_EXPIRE_SECONDS) - .query(&mut *redis_connection)?; - - let redis_refresh_key = format!("user-{}_refresh", id); - - redis::cmd(SET) - .arg(&redis_refresh_key) - .arg(&self.refresh_token) - .arg(EX) - .arg(REFRESH_TOKEN_EXPIRE_SECONDS) - .query(&mut *redis_connection)?; + pub fn store(&self, token_store: &mut TokenStore) -> Result<(), String> { + token_store.insert(&self.request_token, &self.refresh_token) + } +} + +#[derive(Clone, Debug)] +pub struct TokenStoreEntry { + request_token: [u8; TOKEN_LENGTH], + request_ttl: u32, + refresh_token: [u8; TOKEN_LENGTH], + refresh_ttl: u32, + ttl_start: Instant, +} + +impl TokenStoreEntry { + pub fn new(request_token: &String, refresh_token: &String) -> Result { + let request_token = base64::decode(request_token).unwrap(); + let refresh_token = &base64::decode(refresh_token).unwrap(); + if request_token.len() != TOKEN_LENGTH || refresh_token.len() != TOKEN_LENGTH { + return Err("Invalid token length".to_string()); + } + let mut req_token = [0u8; TOKEN_LENGTH]; + let mut ref_token = [0u8; TOKEN_LENGTH]; + req_token.copy_from_slice(&request_token); + ref_token.copy_from_slice(&refresh_token); + + Ok(Self { + request_token: req_token, + refresh_token: ref_token, + request_ttl: REQUEST_TOKEN_EXPIRE_SECONDS, + refresh_ttl: REFRESH_TOKEN_EXPIRE_SECONDS, + ttl_start: Instant::now(), + }) + } + + pub fn request_ttl(&self) -> i32 { + max( + (self.request_ttl - self.ttl_start.elapsed().as_secs() as u32) as i32, + -1, + ) + } + + pub fn refresh_ttl(&self) -> i32 { + max( + (self.refresh_ttl - self.ttl_start.elapsed().as_secs() as u32) as i32, + -1, + ) + } + + pub fn request_token(&self) -> Option { + if self.request_ttl() > 0 { + Some(base64::encode(&self.request_token)) + } else { + None + } + } + + pub fn refresh_token(&self) -> Option { + if self.refresh_ttl() > 0 { + Some(base64::encode(&self.refresh_token)) + } else { + None + } + } + + pub fn set_request_token(&mut self, token: String) -> i32 { + self.request_token + .copy_from_slice(base64::decode(token).unwrap().as_slice()); + self.reset_timer(); + self.request_ttl = REQUEST_TOKEN_EXPIRE_SECONDS; + self.refresh_ttl = REFRESH_TOKEN_EXPIRE_SECONDS; + + self.request_ttl as i32 + } + + fn reset_timer(&mut self) { + self.request_ttl = min(self.request_ttl(), 0) as u32; + self.refresh_ttl = min(self.refresh_ttl(), 0) as u32; + self.ttl_start = Instant::now(); + } +} + +#[derive(Debug)] +pub struct TokenStore { + tokens: HashMap>, +} + +impl TokenStore { + pub fn new() -> Self { + Self { + tokens: HashMap::new(), + } + } + + pub fn get_request_token(&self, request_token: &String) -> Option<&TokenStoreEntry> { + let user_id = get_user_id_from_token(&request_token); + if let Some(user_tokens) = self.tokens.get(&user_id) { + user_tokens.iter().find(|e| { + if let Some(token) = e.request_token() { + &token == request_token + } else { + false + } + }) + } else { + None + } + } + pub fn get_refresh_token(&self, refresh_token: &String) -> Option<&TokenStoreEntry> { + let user_id = get_user_id_from_token(&refresh_token); + if let Some(user_tokens) = self.tokens.get(&user_id) { + user_tokens.iter().find(|e| { + if let Some(token) = e.refresh_token() { + &token == refresh_token + } else { + false + } + }) + } else { + None + } + } + pub fn set_request_token(&mut self, refresh_token: &String, request_token: &String) { + self.clear_expired(); + let user_id = get_user_id_from_token(&request_token); + if let Some(user_tokens) = self.tokens.get_mut(&user_id) { + user_tokens.iter_mut().for_each(|e| { + if let Some(ref_token) = &e.refresh_token() { + if ref_token == refresh_token { + e.set_request_token(request_token.to_string()); + } + } + }); + } + } + + pub fn insert(&mut self, request_token: &String, refresh_token: &String) -> Result<(), String> { + let user_id = get_user_id_from_token(refresh_token); + let user_tokens = if let Some(user_tokens) = self.tokens.get_mut(&user_id) { + user_tokens + } else { + self.tokens.insert(user_id, Vec::new()); + + self.tokens.get_mut(&user_id).unwrap() + }; + let entry = TokenStoreEntry::new(request_token, refresh_token)?; + user_tokens.push(entry); Ok(()) } + + pub fn clear_expired(&mut self) { + for (key, entry) in &self.tokens.clone() { + self.tokens.insert( + *key, + entry + .iter() + .cloned() + .filter(|e| e.refresh_ttl() > 0) + .collect(), + ); + } + } } diff --git a/src/database/user_roles.rs b/src/database/user_roles.rs index cb3c149..0018f78 100644 --- a/src/database/user_roles.rs +++ b/src/database/user_roles.rs @@ -1,5 +1,5 @@ use crate::database::models::Role; -use crate::database::{DatabaseResult, RedisConnection, Table}; +use crate::database::{DatabaseResult, Table}; use crate::utils::error::DBError; use postgres::Client; use std::sync::{Arc, Mutex}; @@ -7,17 +7,12 @@ use std::sync::{Arc, Mutex}; #[derive(Clone)] pub struct UserRoles { database_connection: Arc>, - redis_connection: Arc>, } impl Table for UserRoles { - fn new( - database_connection: Arc>, - redis_connection: Arc>, - ) -> Self { + fn new(database_connection: Arc>) -> Self { Self { database_connection, - redis_connection, } } diff --git a/src/database/users.rs b/src/database/users.rs index 2d5bfe8..926f7c1 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -1,9 +1,9 @@ use crate::database::models::UserRecord; -use crate::database::tokens::SessionTokens; +use crate::database::tokens::{SessionTokens, TokenStore}; use crate::database::user_roles::UserRoles; -use crate::database::{DatabaseResult, RedisConnection, Table}; +use crate::database::{DatabaseResult, Table}; use crate::utils::error::DBError; -use crate::utils::{create_salt, get_user_id_from_token, hash_password, TOKEN_LENGTH}; +use crate::utils::{create_salt, hash_password}; use postgres::Client; use std::sync::{Arc, Mutex}; @@ -12,22 +12,16 @@ use zeroize::{Zeroize, Zeroizing}; #[derive(Clone)] pub struct Users { database_connection: Arc>, - redis_connection: Arc>, user_roles: UserRoles, + token_store: Arc>, } impl Table for Users { - fn new( - database_connection: Arc>, - redis_connection: Arc>, - ) -> Self { + fn new(database_connection: Arc>) -> Self { Self { - user_roles: UserRoles::new( - Arc::clone(&database_connection), - Arc::clone(&redis_connection), - ), + user_roles: UserRoles::new(Arc::clone(&database_connection)), database_connection, - redis_connection, + token_store: Arc::new(Mutex::new(TokenStore::new())), } } @@ -75,7 +69,7 @@ impl Users { Ok(UserRecord::from_ordered_row(&row)) } - pub fn create_get_tokens( + pub fn create_tokens( &self, email: &String, password: &String, @@ -84,45 +78,44 @@ impl Users { let mut connection = self.database_connection.lock().unwrap(); let row = connection.query_one("SELECT id FROM users WHERE email = $1", &[&email])?; let id: i32 = row.get(0); - let mut redis_connection = self.redis_connection.lock().unwrap(); - if let Ok(tokens) = SessionTokens::retrieve(id, &mut redis_connection) { - Ok(tokens) - } else { - let tokens = SessionTokens::new(id); - tokens.store(&mut redis_connection)?; + let tokens = SessionTokens::new(id); + tokens.store(&mut self.token_store.lock().unwrap())?; - Ok(tokens) - } + Ok(tokens) } else { Err(DBError::GenericError("Invalid password".to_string())) } } pub fn validate_request_token(&self, token: &String) -> DatabaseResult<(bool, i32)> { - let id = get_user_id_from_token(token); - let mut redis_connection = self.redis_connection.lock().unwrap(); - let tokens = SessionTokens::retrieve(id, &mut redis_connection)?; + let store = self.token_store.lock().unwrap(); + let entry = store.get_request_token(&token); - Ok((tokens.request_token == *token, tokens.request_ttl)) + if let Some(entry) = entry { + Ok((true, entry.request_ttl())) + } else { + Ok((false, -1)) + } } pub fn validate_refresh_token(&self, token: &String) -> DatabaseResult<(bool, i32)> { - let id = get_user_id_from_token(token); - let mut redis_connection = self.redis_connection.lock().unwrap(); - let tokens = SessionTokens::retrieve(id, &mut redis_connection)?; + let store = self.token_store.lock().unwrap(); + let entry = store.get_refresh_token(&token); - Ok((tokens.refresh_token == *token, tokens.refresh_ttl)) + if let Some(entry) = entry { + Ok((true, entry.refresh_ttl())) + } else { + Ok((false, -1)) + } } pub fn refresh_tokens(&self, refresh_token: &String) -> DatabaseResult { - let id = get_user_id_from_token(&refresh_token); - let mut redis_connection = self.redis_connection.lock().unwrap(); - let mut tokens = SessionTokens::retrieve(id, &mut redis_connection)?; - - if tokens.refresh_token == *refresh_token { + let mut token_store = self.token_store.lock().unwrap(); + let tokens = token_store.get_refresh_token(refresh_token); + if let Some(mut tokens) = tokens.and_then(|t| SessionTokens::from_entry(t)) { tokens.refresh(); - tokens.store(&mut redis_connection)?; + tokens.store(&mut token_store)?; Ok(tokens) } else { diff --git a/src/server/http_server.rs b/src/server/http_server.rs index 6b7b282..b34f40a 100644 --- a/src/server/http_server.rs +++ b/src/server/http_server.rs @@ -17,7 +17,7 @@ pub struct UserHttpServer { #[derive(Debug)] pub struct HTTPError { message: String, - code: usize, + code: u16, } impl Display for HTTPError { @@ -36,8 +36,14 @@ impl From for HTTPError { } } +impl Into for HTTPError { + fn into(self) -> Response { + Response::text(self.message).with_status_code(self.code) + } +} + impl HTTPError { - pub fn new(message: String, code: usize) -> Self { + pub fn new(message: String, code: u16) -> Self { Self { message, code } } } @@ -58,10 +64,10 @@ impl UserHttpServer { let server = Server::new(listen_address, move |request| { router!(request, (POST) (/login) => { - Self::login(&database, request).unwrap_or_else(|e|Response::text(e.to_string())) + Self::login(&database, request).unwrap_or_else(|e|e.into()) }, (POST) (/new-token) => { - Self::new_token(&database, request).unwrap_or_else(|e|Response::text(e.to_string())) + Self::new_token(&database, request).unwrap_or_else(|e|e.into()) }, _ => Response::empty_404() ) @@ -79,7 +85,7 @@ impl UserHttpServer { .map_err(|e| HTTPError::new(e.to_string(), 400))?; let tokens = database .users - .create_get_tokens(&login_request.email, &login_request.password)?; + .create_tokens(&login_request.email, &login_request.password)?; Ok(Response::json(&tokens)) } else { diff --git a/src/utils/error.rs b/src/utils/error.rs index 2d01a16..d17b4c0 100644 --- a/src/utils/error.rs +++ b/src/utils/error.rs @@ -1,11 +1,9 @@ -use redis::RedisError; use serde_postgres::DeError; use std::error; use std::fmt::{self, Display, Formatter}; #[derive(Debug)] pub enum DBError { - Redis(RedisError), Postgres(PostgresError), RecordExists, BCryptError, @@ -27,7 +25,6 @@ impl DBError { DBError::GenericError(g) => g.clone(), DBError::RecordExists => "Record Exists".to_string(), DBError::Postgres(p) => p.to_string(), - DBError::Redis(r) => r.to_string(), DBError::DeserializeError(de) => de.to_string(), DBError::BCryptError => "BCrypt Hash creation error".to_string(), } @@ -42,19 +39,17 @@ impl From for DBError { } } -impl From for DBError { - fn from(other: RedisError) -> Self { - Self::Redis(other) - } -} - impl From for DBError { fn from(other: DeError) -> Self { Self::DeserializeError(other) } } +impl From for DBError { + fn from(other: String) -> Self { + Self::GenericError(other) + } +} + pub type DatabaseClient = postgres::Client; -pub type RedisClient = redis::Client; -pub type RedisConnection = redis::Connection; pub type PostgresError = postgres::Error;