From 672665bda688c221b5f563686400f4d885e6498a Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 21 Sep 2021 14:33:58 +0200 Subject: [PATCH] use lazy_static --- Cargo.lock | 1 + crates/api/src/lib.rs | 2 +- crates/api_common/Cargo.toml | 1 + crates/api_common/src/claims.rs | 31 +++++++++++++++++++++++-------- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c51cc769..60173813f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1629,6 +1629,7 @@ dependencies = [ "chrono", "diesel", "jsonwebtoken", + "lazy_static", "lemmy_db_queries", "lemmy_db_schema", "lemmy_db_views", diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index d50611544..9b32c412b 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -207,7 +207,7 @@ mod tests { #[actix_rt::test] async fn test_should_not_validate_user_token_after_password_change() { let conn = establish_unpooled_connection(); - let db_url = get_database_url_from_env().unwrap_or(Settings::get().get_database_url()); + let db_url = get_database_url_from_env().unwrap_or_else(|_| Settings::get().get_database_url()); let pool = Pool::builder() .build(ConnectionManager::::new(&db_url)) .unwrap(); diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml index 0a24642f1..19dfb652f 100644 --- a/crates/api_common/Cargo.toml +++ b/crates/api_common/Cargo.toml @@ -25,3 +25,4 @@ chrono = { version = "0.4.19", features = ["serde"] } serde_json = { version = "1.0.66", features = ["preserve_order"] } url = "2.2.2" jsonwebtoken = "7.2.0" +lazy_static = "1.4.0" diff --git a/crates/api_common/src/claims.rs b/crates/api_common/src/claims.rs index 22c2b1aba..a30ee0b6e 100644 --- a/crates/api_common/src/claims.rs +++ b/crates/api_common/src/claims.rs @@ -1,10 +1,13 @@ use crate::blocking; use chrono::Utc; +use diesel::PgConnection; use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation}; +use lazy_static::lazy_static; use lemmy_db_queries::{source::secrets::Secrets_, DbPool}; use lemmy_db_schema::source::secrets::Secrets; use lemmy_utils::{settings::structs::Settings, LemmyError}; use serde::{Deserialize, Serialize}; +use std::{ops::Deref, sync::RwLock}; type Jwt = String; @@ -23,7 +26,7 @@ impl Claims { validate_exp: false, ..Validation::default() }; - let secret = get_jwt_secret(pool).await?; + let secret = blocking(pool, move |conn| get_jwt_secret(conn)).await??; let key = DecodingKey::from_secret(secret.as_ref()); Ok(decode::(jwt, &key, &v)?) } @@ -34,15 +37,27 @@ impl Claims { iss: Settings::get().hostname, iat: Utc::now().timestamp(), }; - let key = EncodingKey::from_secret(get_jwt_secret(pool).await?.as_ref()); + + let secret = blocking(pool, move |conn| get_jwt_secret(conn)).await??; + let key = EncodingKey::from_secret(secret.as_ref()); Ok(encode(&Header::default(), &my_claims, &key)?) } } -/// TODO: would be good if we could store the jwt secret in memory, so we dont have to run db -/// queries all the time (which probably affects performance). but its tricky, we cant use a -/// static because it requires a db connection to initialize. -async fn get_jwt_secret(pool: &DbPool) -> Result { - let jwt_secret = blocking(pool, move |conn| Secrets::read(conn)).await??; - Ok(jwt_secret) +lazy_static! { + static ref JWT_SECRET: RwLock> = RwLock::new(None); +} + +fn get_jwt_secret(conn: &PgConnection) -> Result { + let jwt_option: Option = JWT_SECRET.read().unwrap().deref().clone(); + match jwt_option { + Some(j) => Ok(j), + None => { + let jwt = Secrets::read(conn)?; + let jwt_static = JWT_SECRET.write(); + let mut jwt_static = jwt_static.unwrap(); + *jwt_static = Some(jwt.clone()); + Ok(jwt) + } + } }