Administrators can remove two factor authentication

This commit is contained in:
Pierre HUBERT 2022-04-19 17:14:05 +02:00
parent 630ebe2ddd
commit 78d70af510
5 changed files with 44 additions and 10 deletions

View File

@ -11,4 +11,5 @@ body {
.page_body { .page_body {
padding: 3rem; padding: 3rem;
overflow-y: scroll;
} }

View File

@ -60,6 +60,7 @@ pub struct UpdateUserQuery {
admin: Option<String>, admin: Option<String>,
grant_type: String, grant_type: String,
granted_clients: String, granted_clients: String,
two_factor: String,
} }
pub async fn users_route(user: CurrentUser, users: web::Data<Addr<UsersActor>>, update_query: Option<web::Form<UpdateUserQuery>>) -> impl Responder { pub async fn users_route(user: CurrentUser, users: web::Data<Addr<UsersActor>>, update_query: Option<web::Form<UpdateUserQuery>>) -> impl Responder {
@ -80,6 +81,11 @@ 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<_>>();
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,
"custom_clients" => Some(update.0.granted_clients.split(',') "custom_clients" => Some(update.0.granted_clients.split(',')

View File

@ -41,7 +41,7 @@ pub struct User {
pub admin: bool, pub admin: bool,
/// 2FA /// 2FA
pub second_factors: Option<Vec<SecondFactor>>, pub two_factor: Option<Vec<SecondFactor>>,
/// None = all services /// None = all services
/// Some([]) = no service /// Some([]) = no service
@ -64,16 +64,20 @@ impl User {
verify_password(pass, &self.password) verify_password(pass, &self.password)
} }
pub fn add_factor(&mut self, factor: SecondFactor) { pub fn has_two_factor(&self) -> bool {
if self.second_factors.is_none() { self.two_factor.as_ref().map(|f| !f.is_empty()).unwrap_or(false)
self.second_factors = Some(vec![]);
} }
self.second_factors.as_mut().unwrap().push(factor); pub fn add_factor(&mut self, factor: SecondFactor) {
if self.two_factor.is_none() {
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.second_factors.as_mut() { if let Some(f) = self.two_factor.as_mut() {
f.retain(|f| f.id != factor_id); f.retain(|f| f.id != factor_id);
} }
} }
@ -99,7 +103,7 @@ impl Default for User {
need_reset_password: false, need_reset_password: false,
enabled: true, enabled: true,
admin: false, admin: false,
second_factors: Some(vec![]), two_factor: Some(vec![]),
authorized_clients: Some(Vec::new()), authorized_clients: Some(Vec::new()),
} }
} }

View File

@ -68,6 +68,25 @@
</div> </div>
</div> </div>
<!-- Two-Factor authentication -->
<input type="hidden" name="two_factor" value=""/>
{% if u.has_two_factor() %}
<fieldset class="form-group">
<legend class="mt-4">Two factor authentication</legend>
<strong>If you uncheck a factor, it will be DELETED</strong>
{% for f in u.two_factor.as_deref().unwrap_or_default() %}
<div class="form-check">
<label class="form-check-label">
<input type="checkbox" class="form-check-input two-fact-checkbox"
value="{{ f.id.0 }}"
checked=""/>
{{ f.name }} ({{ f.type_str() }})
</label>
</div>
{% endfor %}
</fieldset>
{% endif %}
<!-- Granted clients --> <!-- Granted clients -->
<fieldset class="form-group"> <fieldset class="form-group">
<legend class="mt-4">Granted clients</legend> <legend class="mt-4">Granted clients</legend>
@ -161,11 +180,15 @@
document.querySelector("input[name=granted_clients]").value = authorized_clients; document.querySelector("input[name=granted_clients]").value = authorized_clients;
const factors_to_keep = [...document.querySelectorAll(".two-fact-checkbox")]
.filter(e => e.checked)
.map(e => e.value)
.join(";")
document.querySelector("input[name=two_factor]").value = factors_to_keep;
form.submit(); form.submit();
}); });
</script> </script>
{% endblock content %} {% endblock content %}

View File

@ -23,7 +23,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for f in user.second_factors.as_deref().unwrap_or_default() %} {% for f in user.two_factor.as_deref().unwrap_or_default() %}
<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>