use lazy_static

This commit is contained in:
Felix Ableitner 2021-09-21 14:33:58 +02:00
parent 3516939fd5
commit 48918f362d
4 changed files with 26 additions and 9 deletions

1
Cargo.lock generated
View file

@ -1629,6 +1629,7 @@ dependencies = [
"chrono", "chrono",
"diesel", "diesel",
"jsonwebtoken", "jsonwebtoken",
"lazy_static",
"lemmy_db_queries", "lemmy_db_queries",
"lemmy_db_schema", "lemmy_db_schema",
"lemmy_db_views", "lemmy_db_views",

View file

@ -207,7 +207,7 @@ mod tests {
#[actix_rt::test] #[actix_rt::test]
async fn test_should_not_validate_user_token_after_password_change() { async fn test_should_not_validate_user_token_after_password_change() {
let conn = establish_unpooled_connection(); 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() let pool = Pool::builder()
.build(ConnectionManager::<PgConnection>::new(&db_url)) .build(ConnectionManager::<PgConnection>::new(&db_url))
.unwrap(); .unwrap();

View file

@ -25,3 +25,4 @@ chrono = { version = "0.4.19", features = ["serde"] }
serde_json = { version = "1.0.66", features = ["preserve_order"] } serde_json = { version = "1.0.66", features = ["preserve_order"] }
url = "2.2.2" url = "2.2.2"
jsonwebtoken = "7.2.0" jsonwebtoken = "7.2.0"
lazy_static = "1.4.0"

View file

@ -1,10 +1,13 @@
use crate::blocking; use crate::blocking;
use chrono::Utc; use chrono::Utc;
use diesel::PgConnection;
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, TokenData, Validation}; 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_queries::{source::secrets::Secrets_, DbPool};
use lemmy_db_schema::source::secrets::Secrets; use lemmy_db_schema::source::secrets::Secrets;
use lemmy_utils::{settings::structs::Settings, LemmyError}; use lemmy_utils::{settings::structs::Settings, LemmyError};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ops::Deref, sync::RwLock};
type Jwt = String; type Jwt = String;
@ -23,7 +26,7 @@ impl Claims {
validate_exp: false, validate_exp: false,
..Validation::default() ..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()); let key = DecodingKey::from_secret(secret.as_ref());
Ok(decode::<Claims>(jwt, &key, &v)?) Ok(decode::<Claims>(jwt, &key, &v)?)
} }
@ -34,15 +37,27 @@ impl Claims {
iss: Settings::get().hostname, iss: Settings::get().hostname,
iat: Utc::now().timestamp(), 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)?) 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 lazy_static! {
/// queries all the time (which probably affects performance). but its tricky, we cant use a static ref JWT_SECRET: RwLock<Option<String>> = RwLock::new(None);
/// static because it requires a db connection to initialize. }
async fn get_jwt_secret(pool: &DbPool) -> Result<String, LemmyError> {
let jwt_secret = blocking(pool, move |conn| Secrets::read(conn)).await??; fn get_jwt_secret(conn: &PgConnection) -> Result<String, LemmyError> {
Ok(jwt_secret) let jwt_option: Option<String> = 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)
}
}
} }