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",
"diesel",
"jsonwebtoken",
"lazy_static",
"lemmy_db_queries",
"lemmy_db_schema",
"lemmy_db_views",

View file

@ -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::<PgConnection>::new(&db_url))
.unwrap();

View file

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

View file

@ -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::<Claims>(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<String, LemmyError> {
let jwt_secret = blocking(pool, move |conn| Secrets::read(conn)).await??;
Ok(jwt_secret)
lazy_static! {
static ref JWT_SECRET: RwLock<Option<String>> = RwLock::new(None);
}
fn get_jwt_secret(conn: &PgConnection) -> Result<String, LemmyError> {
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)
}
}
}