admin/users: force delete totp secret, totp backup

This commit is contained in:
Philippe Loctaux 2023-05-04 21:28:07 +02:00
parent 2418c8e124
commit bb2d8fed45
3 changed files with 172 additions and 0 deletions

View file

@ -28,6 +28,8 @@ pub fn routes() -> Vec<Route> {
admin_users_archive, admin_users_archive,
admin_users_password_reset, admin_users_password_reset,
admin_users_paper_key_reset, admin_users_paper_key_reset,
admin_users_totp_secret_disable,
admin_users_totp_backup_delete,
] ]
} }

View file

@ -351,6 +351,7 @@ pub async fn admin_users_paper_key_reset(
.await? .await?
.ok_or_else(|| Error::not_found("Could not find user"))?; .ok_or_else(|| Error::not_found("Could not find user"))?;
// Delete paper key
user.set_paper_key(&mut transaction, None).await?; user.set_paper_key(&mut transaction, None).await?;
transaction.commit().await?; transaction.commit().await?;
@ -366,3 +367,82 @@ pub async fn admin_users_paper_key_reset(
flash_message, flash_message,
)) ))
} }
#[derive(Debug, FromForm)]
pub struct TotpSecretDisableForm {
pub disable: Option<bool>,
}
#[post("/admin/users/<id>/totp_secret", data = "<form>")]
pub async fn admin_users_totp_secret_disable(
_admin_not_current: JwtAdminNotCurrent,
mut db: Connection<Database>,
id: RocketUserID,
form: Form<TotpSecretDisableForm>,
) -> Result<Flash<Redirect>> {
let (flash_kind, flash_message) = match form.disable {
Some(true) => {
let mut transaction = db.begin().await?;
// Get user
let user = User::get_by_id(&mut transaction, &id.0)
.await?
.ok_or_else(|| Error::not_found("Could not find user"))?;
// Delete totp secret
user.set_totp_secret(&mut transaction, None).await?;
// Delete totp backup
user.set_totp_backup(&mut transaction, None).await?;
transaction.commit().await?;
(FlashKind::Success, "TOTP has been disabled.")
}
_ => (FlashKind::Warning, "Nothing to do."),
};
Ok(Flash::new(
Redirect::to(uri!(admin_users_view(id))),
flash_kind,
flash_message,
))
}
#[derive(Debug, FromForm)]
pub struct TotpBackupDeleteForm {
pub delete: Option<bool>,
}
#[post("/admin/users/<id>/totp_backup", data = "<form>")]
pub async fn admin_users_totp_backup_delete(
_admin_not_current: JwtAdminNotCurrent,
mut db: Connection<Database>,
id: RocketUserID,
form: Form<TotpBackupDeleteForm>,
) -> Result<Flash<Redirect>> {
let (flash_kind, flash_message) = match form.delete {
Some(true) => {
let mut transaction = db.begin().await?;
// Get user
let user = User::get_by_id(&mut transaction, &id.0)
.await?
.ok_or_else(|| Error::not_found("Could not find user"))?;
// Delete totp backup
user.set_totp_backup(&mut transaction, None).await?;
transaction.commit().await?;
(FlashKind::Success, "TOTP backup has been deleted.")
}
_ => (FlashKind::Warning, "Nothing to do."),
};
Ok(Flash::new(
Redirect::to(uri!(admin_users_view(id))),
flash_kind,
flash_message,
))
}

View file

@ -429,6 +429,96 @@
</div> </div>
</div> </div>
<!-- TOTP secret reset -->
<div class="modal modal-blur" tabindex="-1" id="modal-totp-secret">
<div class="modal-dialog modal-sm modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-status bg-danger"></div>
<form action="{{ local.id }}/totp_secret" method="post">
<div class="modal-body text-center py-4">
<div class="text-danger mb-2">
{% include "icons/alert-triangle-large" %}
</div>
<h3>Do you want to disable TOTP for this user?</h3>
<div class="mt-2">This will also delete the TOTP backup.</div>
</div>
<div class="modal-footer">
<div class="w-100">
<div class="row">
<div class="col">
<a href="#" class="btn w-100" data-bs-dismiss="modal">Cancel</a>
</div>
<div class="col">
<button type="submit" name="disable" value="true"
class="btn btn-danger w-100">
Disable TOTP
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<!-- TOTP backup delete -->
<div class="modal modal-blur" tabindex="-1" id="modal-totp-backup">
<div class="modal-dialog modal-sm modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-status bg-danger"></div>
<form action="{{ local.id }}/totp_backup" method="post">
<div class="modal-body text-center py-4">
<div class="text-danger mb-2">
{% include "icons/alert-triangle-large" %}
</div>
<h3>Do you want to delete the TOTP backup for this user?</h3>
</div>
<div class="modal-footer">
<div class="w-100">
<div class="row">
<div class="col">
<a href="#" class="btn w-100" data-bs-dismiss="modal">Cancel</a>
</div>
<div class="col">
<button type="submit" name="delete" value="true"
class="btn btn-danger w-100">
Delete backup
</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock content %} {% endblock content %}
{% block libs_js %} {% block libs_js %}