Skip to content

Commit c341428

Browse files
committed
Fix the users_file user store - it now live-reads the file on every operation
1 parent 92483f5 commit c341428

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

src/config.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::CONFIG;
2121
use crate::database::{ConfigKVRow, Database};
2222
use crate::service::Services;
2323
use crate::user::User;
24-
use crate::user_store::{SQLUserStore, StaticUserStore, UserStoreKind};
24+
use crate::user_store::{FileUserStore, SQLUserStore, StaticUserStore, UserStoreKind};
2525
// use crate::user_store::{SQLUserStore, StaticUserStore, UserStoreKind};
2626

2727
/// The actual, deserialized config data
@@ -260,11 +260,8 @@ impl Config {
260260
)));
261261
}
262262

263-
if self.users_file.is_some() {
264-
// TODO: While this is correct since during reload we shove the users to the store, it's not right
265-
return Ok(UserStoreKind::Static(StaticUserStore::new(
266-
self.users.clone(),
267-
)));
263+
if let Some(users_file) = self.users_file.clone() {
264+
return Ok(UserStoreKind::File(FileUserStore::new(users_file)));
268265
}
269266

270267
if let Some(url) = self.users_sql_url.clone() {

src/user_store.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::path::{Path, PathBuf};
2+
13
use serde::{Deserialize, Serialize};
24
use sqlx::Row as _;
35
use tracing::*;
@@ -12,6 +14,7 @@ pub trait UserStore: Send + Sync {
1214
#[derive(Debug, Clone)]
1315
pub enum UserStoreKind {
1416
Static(StaticUserStore),
17+
File(FileUserStore),
1518
SQL(SQLUserStore),
1619
}
1720

@@ -20,6 +23,7 @@ impl UserStore for UserStoreKind {
2023
async fn from_email(&mut self, email: &str) -> Option<User> {
2124
match self {
2225
UserStoreKind::Static(store) => store.from_email(email).await,
26+
UserStoreKind::File(store) => store.from_email(email).await,
2327
UserStoreKind::SQL(store) => store.from_email(email).await,
2428
}
2529
}
@@ -30,7 +34,7 @@ pub struct StaticUserStore(Vec<User>);
3034

3135
impl StaticUserStore {
3236
pub fn new(users: Vec<User>) -> Self {
33-
StaticUserStore(users)
37+
Self(users)
3438
}
3539
}
3640

@@ -41,6 +45,36 @@ impl UserStore for StaticUserStore {
4145
}
4246
}
4347

48+
#[derive(Debug, Clone, Serialize, Deserialize)]
49+
pub struct FileUserStore(String);
50+
51+
impl FileUserStore {
52+
pub fn new(path: String) -> Self {
53+
Self(path)
54+
}
55+
}
56+
57+
#[async_trait::async_trait]
58+
impl UserStore for FileUserStore {
59+
async fn from_email(&mut self, email: &str) -> Option<User> {
60+
let users_contents = match std::fs::read_to_string(self.0.clone()) {
61+
Ok(contents) => contents,
62+
Err(e) => {
63+
error!("Failed to read users file: {}", e);
64+
return None;
65+
}
66+
};
67+
let users = match serde_yaml::from_str::<Vec<User>>(&users_contents) {
68+
Ok(users) => users,
69+
Err(e) => {
70+
error!("Failed to parse users file: {}", e);
71+
return None;
72+
}
73+
};
74+
users.iter().find(|user| user.email == email).cloned()
75+
}
76+
}
77+
4478
#[derive(Debug, Clone)]
4579
pub struct SQLUserStore {
4680
conn: sqlx::AnyPool,

0 commit comments

Comments
 (0)