Skip to content

Commit f14da48

Browse files
authored
Merge pull request #202 from dzervas/codex/add-user-definitions-from-separate-file
Support loading users from external user file
2 parents c49ed41 + c59957e commit f14da48

5 files changed

Lines changed: 87 additions & 41 deletions

File tree

config.sample.yaml

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Apart from oidc_clients and users, the following are the default values
2-
# To create a new config, just set the `users` and any other settings you want to change
2+
# To create a new config, just set the `users` (or point to `users_file`) and any other settings you want to change
33
database_url: database.db
44

55
# Host that the server will listen on
@@ -63,23 +63,14 @@ request_content_type: application/x-www-form-urlencoded
6363
webauthn_enable: true
6464

6565
# List of the users that can authenticate using the service
66-
users:
67-
- username: valid
68-
name: Valid User
69-
email: valid@example.com
70-
realms:
71-
- example
72-
- username: integration
73-
email: valid-integration@example.com
74-
name: Integration User
75-
realms:
76-
- example
77-
- public
78-
- username: admin
79-
email: admin@example.com
80-
name: Admin User
81-
realms:
82-
- all # `all` is a special realm that gives access to all services
66+
# You can either list them here or load them from another file using `users_file`
67+
users_file: users.sample.yaml
68+
# users:
69+
# - username: valid
70+
# name: Valid User
71+
# email: valid@example.com
72+
# realms:
73+
# - example
8374

8475
# Services that can use magicentry
8576
services:

docs/configuration.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,23 @@ users:
3434
- example
3535
- public
3636
```
37+
38+
Alternatively, you can reference the users from a separate file using `users_file`:
39+
40+
`config.yaml`
41+
42+
```yaml
43+
listen_host: 0.0.0.0
44+
request_enable: true
45+
users_file: users.yaml
46+
```
47+
48+
`users.yaml`
49+
50+
```yaml
51+
- username: admin
52+
name: Admin User
53+
email: admin@example.com
54+
realms:
55+
- all
56+
```

docs/installation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ config:
8484
realms:
8585
- myservice
8686

87+
# Users allowed to authenticate (can also be provided via `users_file`)
8788
users:
8889
- name: My Awesome Name
8990
email: awesome@example.com

src/config.rs

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ pub struct ConfigFile {
6262
pub request_url: String,
6363
pub request_method: String,
6464
pub request_data: Option<String>,
65-
pub request_content_type: String,
65+
pub request_content_type: String,
6666

67-
pub webauthn_enable: bool,
67+
pub webauthn_enable: bool,
6868

69-
// pub force_https_redirects: bool,
70-
71-
pub users: Vec<User>,
72-
pub services: Services,
69+
// pub force_https_redirects: bool,
70+
/// Path to a file containing the user definitions
71+
pub users_file: Option<String>,
72+
pub users: Vec<User>,
73+
pub services: Services,
7374
}
7475

7576
impl Default for ConfigFile {
@@ -111,14 +112,15 @@ impl Default for ConfigFile {
111112
request_data : Some("to={email}&subject={title} Login&body=Click the link to login: <a href=\"{magic_link}\">Login</a>&type=text/html".to_string()),
112113
request_content_type: "application/x-www-form-urlencoded".to_string(),
113114

114-
webauthn_enable: true,
115+
webauthn_enable: true,
115116

116-
// force_https_redirects: true,
117+
// force_https_redirects: true,
117118

118-
users: vec![],
119-
services: Services(vec![]),
120-
}
121-
}
119+
users_file: None,
120+
users: vec![],
121+
services: Services(vec![]),
122+
}
123+
}
122124
}
123125

124126
impl ConfigFile {
@@ -150,11 +152,17 @@ impl ConfigFile {
150152
/// Note that live-updating the CONFIG_FILE environment variable
151153
/// is **NOT** supported
152154
pub async fn reload() -> crate::error::Result<()> {
153-
let mut config = CONFIG.write().await;
154-
log::info!("Reloading config from {}", CONFIG_FILE.as_str());
155-
*config = serde_yaml::from_str::<ConfigFile>(&std::fs::read_to_string(CONFIG_FILE.as_str())?)?;
156-
Ok(())
157-
}
155+
let mut config = CONFIG.write().await;
156+
log::info!("Reloading config from {}", CONFIG_FILE.as_str());
157+
let mut new_config =
158+
serde_yaml::from_str::<ConfigFile>(&std::fs::read_to_string(CONFIG_FILE.as_str())?)?;
159+
if let Some(users_file) = &new_config.users_file {
160+
new_config.users =
161+
serde_yaml::from_str::<Vec<User>>(&std::fs::read_to_string(users_file)?)?;
162+
}
163+
*config = new_config;
164+
Ok(())
165+
}
158166

159167
/// Set up a file watcher that fires the [reload](ConfigFile::reload) method so
160168
/// that config file changes get automatically picked up
@@ -174,12 +182,22 @@ impl ConfigFile {
174182
}, watcher_config)
175183
.expect("Failed to create watcher for the config file");
176184

177-
watcher
178-
.watch(Path::new(CONFIG_FILE.as_str()), notify::RecursiveMode::NonRecursive)
179-
.expect("Failed to watch config file for changes");
180-
181-
watcher
182-
}
185+
watcher
186+
.watch(Path::new(CONFIG_FILE.as_str()), notify::RecursiveMode::NonRecursive)
187+
.expect("Failed to watch config file for changes");
188+
189+
if let Some(users_file) = CONFIG
190+
.try_read()
191+
.ok()
192+
.and_then(|c| c.users_file.clone())
193+
{
194+
watcher
195+
.watch(Path::new(&users_file), notify::RecursiveMode::NonRecursive)
196+
.expect("Failed to watch users file for changes");
197+
}
198+
199+
watcher
200+
}
183201

184202
/// Read the SAML certificate from the [saml_cert_pem_path](ConfigFile::saml_cert_pem_path)
185203
/// filepath

users.sample.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
- username: valid
2+
name: Valid User
3+
email: valid@example.com
4+
realms:
5+
- example
6+
- username: integration
7+
email: valid-integration@example.com
8+
name: Integration User
9+
realms:
10+
- example
11+
- public
12+
- username: admin
13+
email: admin@example.com
14+
name: Admin User
15+
realms:
16+
- all # `all` is a special realm that gives access to all services

0 commit comments

Comments
 (0)