Compare commits

...

2 Commits

5 changed files with 20 additions and 26 deletions

View File

@ -81,10 +81,9 @@ pub async fn users_route(user: CurrentUser, users: web::Data<Addr<UsersActor>>,
user.enabled = update.0.enabled.is_some(); user.enabled = update.0.enabled.is_some();
user.admin = update.0.admin.is_some(); user.admin = update.0.admin.is_some();
if let Some(factors) = user.two_factor.as_mut() { let factors_to_keep = update.0.two_factor.split(';').collect::<Vec<_>>();
let factors_to_keep = update.0.two_factor.split(';').collect::<Vec<_>>(); user.two_factor.retain(|f| factors_to_keep.contains(&f.id.0.as_str()));
factors.retain(|f| factors_to_keep.contains(&f.id.0.as_str()));
}
user.authorized_clients = match update.0.grant_type.as_str() { user.authorized_clients = match update.0.grant_type.as_str() {
"all_clients" => None, "all_clients" => None,

View File

@ -6,7 +6,7 @@ use crate::actors::users_actor;
use crate::actors::users_actor::UsersActor; use crate::actors::users_actor::UsersActor;
use crate::data::current_user::CurrentUser; use crate::data::current_user::CurrentUser;
use crate::data::totp_key::TotpKey; use crate::data::totp_key::TotpKey;
use crate::data::user::{FactorID, SecondFactor, SecondFactorType, User}; use crate::data::user::{FactorID, TwoFactor, TwoFactorType, User};
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
pub struct AddTOTPRequest { pub struct AddTOTPRequest {
@ -31,10 +31,10 @@ pub async fn save_totp_factor(user: CurrentUser, form: web::Json<AddTOTPRequest>
} }
let mut user = User::from(user); let mut user = User::from(user);
user.add_factor(SecondFactor { user.add_factor(TwoFactor {
id: FactorID(Uuid::new_v4().to_string()), id: FactorID(Uuid::new_v4().to_string()),
name: form.0.factor_name, name: form.0.factor_name,
kind: SecondFactorType::TOTP(key), kind: TwoFactorType::TOTP(key),
}); });
let res = users.send(users_actor::UpdateUserRequest(user)).await.unwrap().0; let res = users.send(users_actor::UpdateUserRequest(user)).await.unwrap().0;

View File

@ -9,21 +9,21 @@ pub type UserID = String;
pub struct FactorID(pub String); pub struct FactorID(pub String);
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub enum SecondFactorType { pub enum TwoFactorType {
TOTP(TotpKey) TOTP(TotpKey)
} }
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct SecondFactor { pub struct TwoFactor {
pub id: FactorID, pub id: FactorID,
pub name: String, pub name: String,
pub kind: SecondFactorType, pub kind: TwoFactorType,
} }
impl SecondFactor { impl TwoFactor {
pub fn type_str(&self) -> &'static str { pub fn type_str(&self) -> &'static str {
match self.kind { match self.kind {
SecondFactorType::TOTP(_) => "Authenticator app" TwoFactorType::TOTP(_) => "Authenticator app"
} }
} }
} }
@ -41,7 +41,8 @@ pub struct User {
pub admin: bool, pub admin: bool,
/// 2FA /// 2FA
pub two_factor: Option<Vec<SecondFactor>>, #[serde(default)]
pub two_factor: Vec<TwoFactor>,
/// None = all services /// None = all services
/// Some([]) = no service /// Some([]) = no service
@ -65,21 +66,15 @@ impl User {
} }
pub fn has_two_factor(&self) -> bool { pub fn has_two_factor(&self) -> bool {
self.two_factor.as_ref().map(|f| !f.is_empty()).unwrap_or(false) !self.two_factor.is_empty()
} }
pub fn add_factor(&mut self, factor: SecondFactor) { pub fn add_factor(&mut self, factor: TwoFactor) {
if self.two_factor.is_none() { self.two_factor.push(factor);
self.two_factor = Some(vec![]);
}
self.two_factor.as_mut().unwrap().push(factor);
} }
pub fn remove_factor(&mut self, factor_id: FactorID) { pub fn remove_factor(&mut self, factor_id: FactorID) {
if let Some(f) = self.two_factor.as_mut() { self.two_factor.retain(|f| f.id != factor_id);
f.retain(|f| f.id != factor_id);
}
} }
} }
@ -103,7 +98,7 @@ impl Default for User {
need_reset_password: false, need_reset_password: false,
enabled: true, enabled: true,
admin: false, admin: false,
two_factor: Some(vec![]), two_factor: vec![],
authorized_clients: Some(Vec::new()), authorized_clients: Some(Vec::new()),
} }
} }

View File

@ -74,7 +74,7 @@
<fieldset class="form-group"> <fieldset class="form-group">
<legend class="mt-4">Two factor authentication</legend> <legend class="mt-4">Two factor authentication</legend>
<strong>If you uncheck a factor, it will be DELETED</strong> <strong>If you uncheck a factor, it will be DELETED</strong>
{% for f in u.two_factor.as_deref().unwrap_or_default() %} {% for f in u.two_factor %}
<div class="form-check"> <div class="form-check">
<label class="form-check-label"> <label class="form-check-label">
<input type="checkbox" class="form-check-input two-fact-checkbox" <input type="checkbox" class="form-check-input two-fact-checkbox"

View File

@ -23,7 +23,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for f in user.two_factor.as_deref().unwrap_or_default() %} {% for f in user.two_factor %}
<tr id="factor-{{ f.id.0 }}"> <tr id="factor-{{ f.id.0 }}">
<td>{{ f.type_str() }}</td> <td>{{ f.type_str() }}</td>
<td>{{ f.name }}</td> <td>{{ f.name }}</td>