Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: auth cache #643

Merged
merged 28 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
32ccc0a
feat: initial commit of auth cache
oddgrd Feb 19, 2023
619fd24
fix: expiration logic
oddgrd Feb 20, 2023
1865085
refactor: switch dashmap to ttlc_cache
oddgrd Feb 20, 2023
a5f2054
feat: rewrite the cache as a tower service
oddgrd Feb 20, 2023
4d7e38b
feat: add cache layer to convert_cookie
oddgrd Feb 20, 2023
a797c14
feat: cachemanagement trait
oddgrd Feb 20, 2023
959cd92
feat: refactor layer to be applied to router not specific handlers
oddgrd Feb 21, 2023
ffd0ab1
refactor: move comment
oddgrd Feb 21, 2023
678b0d5
feat: set cache in cachelayer, invalidate cached jwt on logout
oddgrd Feb 21, 2023
5dc8f0a
feat: error handling in the cache layer
oddgrd Feb 21, 2023
ff86f99
Merge branch 'main' into feature/eng-439-cache-layer
oddgrd Feb 22, 2023
e783901
feat: implement cache layer on gateway
oddgrd Feb 22, 2023
5abde31
refactor: remove the cache from auth
oddgrd Feb 22, 2023
650e541
refactor: revert changes needed for cache in auth
oddgrd Feb 22, 2023
17c78f3
feat: invalidate jwt on logout calls
oddgrd Feb 22, 2023
45baf3e
refactor: clean up logout cache invalidation
oddgrd Feb 22, 2023
ec9702a
refactor: remove cache from shared state
oddgrd Feb 22, 2023
9c9b27f
refactor: remove comment
oddgrd Feb 22, 2023
ae8dd08
feat: add prepare.sh to auth
oddgrd Feb 22, 2023
541144c
feat: move cache to auth layer
oddgrd Feb 22, 2023
678cce2
feat: invalidate cache on logout
oddgrd Feb 23, 2023
a6265c2
refactor: error handling in extract expiration
oddgrd Feb 23, 2023
26b591d
refactor: remove cache-layer, add comment
oddgrd Feb 24, 2023
a4fad11
docs: add comment about logout cache invalidation
oddgrd Feb 24, 2023
b6ab3c5
refactor: cachemanager new fn, remove comment
oddgrd Feb 24, 2023
7e34b4f
fix: make sure cookie is shuttle cookie
oddgrd Feb 24, 2023
f0aa8cb
feat: add buffer to cache expiration
oddgrd Feb 25, 2023
d0e2a3a
fix: fmt
oddgrd Feb 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 16 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions auth/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,30 @@ anyhow = { workspace = true }
async-trait = { workspace = true }
oddgrd marked this conversation as resolved.
Show resolved Hide resolved
axum = { workspace = true, features = ["headers"] }
axum-sessions = "0.4.1"
chrono = { workspace = true, features = ["serde"] }
clap = { workspace = true }
http = { workspace = true }
jsonwebtoken = { workspace = true}
hyper = { workspace = true }
jsonwebtoken = { workspace = true }
opentelemetry = { workspace = true }
opentelemetry-datadog = { workspace = true }
rand = { workspace = true }
ring = { workspace = true }
serde = { workspace = true, features = [ "derive" ] }
sqlx = { version = "0.6.2", features = [ "sqlite", "json", "runtime-tokio-native-tls", "migrate" ] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
sqlx = { version = "0.6.2", features = ["sqlite", "json", "runtime-tokio-native-tls", "migrate"] }
strum = { workspace = true }
thiserror = { workspace = true }
tokio = { version = "1.22.0", features = [ "full" ] }
tokio = { version = "1.22.0", features = ["full"] }
tower = { workspace = true, features = ["util"] }
tracing = { workspace = true }
tracing-opentelemetry = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
ttl_cache = "0.5.1"

[dependencies.shuttle-common]
workspace = true
features = ["backend", "models"]

[dev-dependencies]
axum-extra = { version = "0.5.0", features = ["cookie"] }
hyper = { workspace = true }
serde_json = { workspace = true }
tower = { workspace = true, features = ["util"] }
46 changes: 41 additions & 5 deletions auth/src/api/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,33 @@ use shuttle_common::{
request_span,
};
use sqlx::SqlitePool;
use std::sync::RwLock;
use tracing::field;
use ttl_cache::TtlCache;

use crate::{
secrets::{EdDsaManager, KeyManager},
user::{UserManagement, UserManager},
COOKIE_EXPIRATION,
};

use super::handlers::{
convert_cookie, convert_key, get_public_key, get_user, login, logout, post_user, refresh_token,
use super::{
cache::{CacheLayer, CacheManagement, CacheManager},
handlers::{
convert_cookie, convert_key, get_public_key, get_user, login, logout, post_user,
refresh_token,
},
};

pub type UserManagerState = Arc<Box<dyn UserManagement>>;
pub type KeyManagerState = Arc<Box<dyn KeyManager>>;
pub type CacheManagerState = Arc<Box<dyn CacheManagement>>;

#[derive(Clone)]
pub struct RouterState {
pub user_manager: UserManagerState,
pub key_manager: KeyManagerState,
pub cache_manager: CacheManagerState,
}

// Allow getting a user management state directly
Expand All @@ -47,10 +56,18 @@ impl FromRef<RouterState> for KeyManagerState {
}
}

// Allow getting a cache state directly
impl FromRef<RouterState> for CacheManagerState {
fn from_ref(router_state: &RouterState) -> Self {
router_state.cache_manager.clone()
}
}

pub struct ApiBuilder {
router: Router<RouterState>,
pool: Option<SqlitePool>,
session_layer: Option<SessionLayer<MemoryStore>>,
cache: Option<Arc<RwLock<TtlCache<String, String>>>>,
}

impl Default for ApiBuilder {
Expand Down Expand Up @@ -87,6 +104,7 @@ impl ApiBuilder {
router,
pool: None,
session_layer: None,
cache: None,
}
}

Expand All @@ -102,24 +120,42 @@ impl ApiBuilder {
self.session_layer = Some(
SessionLayer::new(store, &secret)
.with_cookie_name("shuttle.sid")
.with_session_ttl(Some(std::time::Duration::from_secs(60 * 60 * 24))) // One day
.with_session_ttl(Some(COOKIE_EXPIRATION)) // One day
.with_secure(true),
);

self
}

pub fn with_cache(mut self) -> Self {
let cache = Arc::new(RwLock::new(TtlCache::new(1000)));

self.cache = Some(cache);

self
}

pub fn into_router(self) -> Router {
let pool = self.pool.expect("an sqlite pool is required");
let session_layer = self.session_layer.expect("a session layer is required");
let cache = self.cache.expect("a cache is required");

let cache_manager = CacheManager { cache };
let user_manager = UserManager { pool };
let key_manager = EdDsaManager::new();

self.router.layer(session_layer).with_state(RouterState {
let state = RouterState {
user_manager: Arc::new(Box::new(user_manager)),
key_manager: Arc::new(Box::new(key_manager)),
})
cache_manager: Arc::new(Box::new(cache_manager)),
};

self.router
.layer(session_layer)
.layer(CacheLayer {
state: state.clone(),
})
.with_state(state)
}
}

Expand Down
Loading