diff --git a/migrations/2023-11-28-150402_fediwiki_setup/down.sql b/migrations/2023-11-28-150402_fediwiki_setup/down.sql index 06c62b9..abbbd6f 100644 --- a/migrations/2023-11-28-150402_fediwiki_setup/down.sql +++ b/migrations/2023-11-28-150402_fediwiki_setup/down.sql @@ -5,3 +5,4 @@ drop table instance_follow; drop table local_user; drop table person; drop table instance; +drop table jwt_secret; diff --git a/migrations/2023-11-28-150402_fediwiki_setup/up.sql b/migrations/2023-11-28-150402_fediwiki_setup/up.sql index dbb0cbc..7529199 100644 --- a/migrations/2023-11-28-150402_fediwiki_setup/up.sql +++ b/migrations/2023-11-28-150402_fediwiki_setup/up.sql @@ -59,4 +59,14 @@ create table conflict ( creator_id int REFERENCES local_user ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, article_id int REFERENCES article ON UPDATE CASCADE ON DELETE CASCADE NOT NULL, previous_version_id uuid not null -); \ No newline at end of file +); + +-- generate a jwt secret +CREATE EXTENSION IF NOT EXISTS pgcrypto; + +CREATE TABLE jwt_secret ( + id serial PRIMARY KEY, + secret varchar NOT NULL DEFAULT gen_random_uuid () +); + +INSERT INTO jwt_secret DEFAULT VALUES; diff --git a/src/api/user.rs b/src/api/user.rs index d70a893..a14178d 100644 --- a/src/api/user.rs +++ b/src/api/user.rs @@ -1,5 +1,5 @@ use crate::database::user::{DbLocalUser, DbPerson, LocalUserView}; -use crate::database::MyDataHandle; +use crate::database::{read_jwt_secret, MyDataHandle}; use crate::error::MyResult; use activitypub_federation::config::Data; use anyhow::anyhow; @@ -25,9 +25,6 @@ pub struct Claims { pub exp: u64, } -// TODO: move to config -const SECRET: &[u8] = "secret".as_bytes(); - pub(in crate::api) fn generate_login_token( local_user: DbLocalUser, data: &Data, @@ -40,14 +37,16 @@ pub(in crate::api) fn generate_login_token( exp: get_current_timestamp(), }; - let key = EncodingKey::from_secret(SECRET); + let secret = read_jwt_secret(data)?; + let key = EncodingKey::from_secret(secret.as_bytes()); let jwt = encode(&Header::default(), &claims, &key)?; Ok(LoginResponse { jwt }) } pub async fn validate(jwt: &str, data: &Data) -> MyResult { let validation = Validation::default(); - let key = DecodingKey::from_secret(SECRET); + let secret = read_jwt_secret(data)?; + let key = DecodingKey::from_secret(secret.as_bytes()); let claims = decode::(jwt, &key, &validation)?; DbPerson::read_local_from_id(claims.claims.sub.parse()?, data) } diff --git a/src/database/mod.rs b/src/database/mod.rs index ffa8c14..4761b63 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -1,8 +1,12 @@ use crate::database::article::DbArticle; - use diesel::PgConnection; use std::ops::Deref; use std::sync::{Arc, Mutex}; +pub type MyDataHandle = MyData; +use crate::database::schema::jwt_secret; +use crate::error::MyResult; +use diesel::{QueryDsl, RunQueryDsl}; +use std::ops::DerefMut; pub mod article; pub mod conflict; @@ -25,4 +29,9 @@ impl Deref for MyData { } } -pub type MyDataHandle = MyData; +pub fn read_jwt_secret(conn: &Mutex) -> MyResult { + let mut conn = conn.lock().unwrap(); + Ok(jwt_secret::table + .select(jwt_secret::dsl::secret) + .first(conn.deref_mut())?) +} diff --git a/src/database/schema.rs b/src/database/schema.rs index 74cebb1..3983181 100644 --- a/src/database/schema.rs +++ b/src/database/schema.rs @@ -59,6 +59,13 @@ diesel::table! { } } +diesel::table! { + jwt_secret (id) { + id -> Int4, + secret -> Varchar, + } +} + diesel::table! { local_user (id) { id -> Int4, @@ -81,6 +88,13 @@ diesel::table! { } } +diesel::table! { + secret (id) { + id -> Int4, + jwt_secret -> Varchar, + } +} + diesel::joinable!(article -> instance (instance_id)); diesel::joinable!(conflict -> article (article_id)); diesel::joinable!(conflict -> local_user (creator_id)); @@ -96,6 +110,8 @@ diesel::allow_tables_to_appear_in_same_query!( edit, instance, instance_follow, + jwt_secret, local_user, person, + secret, );