settings/security: generate paper key
This commit is contained in:
parent
c1daa34f2c
commit
a67c7559b9
12 changed files with 183 additions and 4 deletions
|
|
@ -39,7 +39,8 @@ impl Icon {
|
|||
"alert-triangle-large", AlertTriangleLarge, r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-lg icon-tabler icon-tabler-alert-triangle" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M10.24 3.957l-8.422 14.06a1.989 1.989 0 0 0 1.7 2.983h16.845a1.989 1.989 0 0 0 1.7 -2.983l-8.423 -14.06a1.989 1.989 0 0 0 -3.4 0z"></path><path d="M12 9v4"></path><path d="M12 17h.01"></path></svg>"#,
|
||||
"id-badge-2", IdBadge2, r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-id-badge-2" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M7 12h3v4h-3z"></path><path d="M10 6h-6a1 1 0 0 0 -1 1v12a1 1 0 0 0 1 1h16a1 1 0 0 0 1 -1v-12a1 1 0 0 0 -1 -1h-6"></path><path d="M10 3m0 1a1 1 0 0 1 1 -1h2a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1z"></path><path d="M14 16h2"></path><path d="M14 12h4"></path></svg>"#,
|
||||
"user", User, r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-user" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0"></path><path d="M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2"></path></svg>"#,
|
||||
"at", At, r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-at" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 12m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0"></path><path d="M16 12v1.5a2.5 2.5 0 0 0 5 0v-1.5a9 9 0 1 0 -5.5 8.28"></path></svg>"#
|
||||
"at", At, r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-at" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M12 12m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0"></path><path d="M16 12v1.5a2.5 2.5 0 0 0 5 0v-1.5a9 9 0 1 0 -5.5 8.28"></path></svg>"#,
|
||||
"paperclip-large", PaperclipLarge, r#"<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-lg icon-tabler icon-tabler-paperclip" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M15 7l-6.5 6.5a1.5 1.5 0 0 0 3 3l6.5 -6.5a3 3 0 0 0 -6 -6l-6.5 6.5a4.5 4.5 0 0 0 9 9l6.5 -6.5"></path></svg>"#
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,6 +61,7 @@ pub fn icons_to_templates(tera: &mut Tera) {
|
|||
Icon::IdBadge2,
|
||||
Icon::User,
|
||||
Icon::At,
|
||||
Icon::PaperclipLarge,
|
||||
];
|
||||
|
||||
// For each icon, it will output: ("icons/name", "<svg>...</svg>")
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub fn routes() -> Vec<Route> {
|
|||
user_settings_personal_form,
|
||||
user_settings_security,
|
||||
user_settings_security_logout_everywhere,
|
||||
user_settings_security_paper_key,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ use crate::tokens::{
|
|||
JWT_COOKIE_NAME, JWT_DURATION_MINUTES, REFRESH_TOKEN_COOKIE_NAME, REFRESH_TOKEN_DURATION_DAYS,
|
||||
};
|
||||
use apps::App;
|
||||
use hash::PaperKey;
|
||||
use jwt::database::Key;
|
||||
use jwt::PrivateKey;
|
||||
use refresh_tokens::RefreshToken;
|
||||
|
|
@ -126,3 +127,52 @@ pub async fn user_settings_security_logout_everywhere(
|
|||
flash_message,
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug, FromForm)]
|
||||
pub struct PaperKeyForm {
|
||||
pub generate_paper_key: bool,
|
||||
}
|
||||
|
||||
#[post("/settings/security/paper_key", data = "<form>")]
|
||||
pub async fn user_settings_security_paper_key(
|
||||
mut db: Connection<Database>,
|
||||
jwt_user: JwtUser,
|
||||
form: Form<PaperKeyForm>,
|
||||
) -> Result<Flash<Redirect>> {
|
||||
let (flash_kind, flash_message) = if form.generate_paper_key {
|
||||
// Create new paper key
|
||||
let paper_key = task::spawn_blocking(PaperKey::generate).await??;
|
||||
|
||||
let mut transaction = db.begin().await?;
|
||||
|
||||
// Get user info
|
||||
let user = User::get_by_login(&mut transaction, &jwt_user.0.subject)
|
||||
.await?
|
||||
.ok_or_else(|| Error::not_found("Could not find user"))?;
|
||||
|
||||
// Save paper key
|
||||
user.set_paper_key(&mut transaction, Some(&paper_key))
|
||||
.await?;
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
// Safety: safe to unwrap, the value is present
|
||||
let plain_paper_key = paper_key.plain().unwrap();
|
||||
|
||||
(
|
||||
FlashKind::Success,
|
||||
format!(
|
||||
"Your paper key has been generated. It will only be shown once!\
|
||||
<div class=\"mt-1 user-select-all\">{plain_paper_key}</div>"
|
||||
),
|
||||
)
|
||||
} else {
|
||||
(FlashKind::Warning, "Nothing to do.".into())
|
||||
};
|
||||
|
||||
Ok(Flash::new(
|
||||
Redirect::to(uri!(user_settings_security)),
|
||||
flash_kind,
|
||||
flash_message,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
<p class="card-subtitle">
|
||||
You can use your paper key to reset your password if you forget it.</p>
|
||||
<div>
|
||||
<a href="#" class="btn">
|
||||
<a class="btn" data-bs-toggle="modal" data-bs-target="#modal-paper-key">
|
||||
Generate new paper key
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -79,6 +79,51 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Paper key modal -->
|
||||
<div class="modal modal-blur" tabindex="-1" id="modal-paper-key">
|
||||
<div class="modal-dialog modal-sm modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
|
||||
<div class="modal-status bg-info"></div>
|
||||
|
||||
<div class="modal-body text-center py-4">
|
||||
|
||||
<div class="text-info mb-2">
|
||||
{% include "icons/paperclip-large" %}
|
||||
</div>
|
||||
|
||||
<h3>Generate new paper key</h3>
|
||||
<div class="mt-2">A new paper key will be generated for your account.</div>
|
||||
<div class="mt-2">This action will revoke your previous paper key if you had one.</div>
|
||||
<div class="mt-2">Keep your paper key in a safe place!</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">
|
||||
<form action="./security/paper_key" method="post">
|
||||
<button type="submit" name="generate_paper_key" value="true"
|
||||
class="btn btn-primary w-100">
|
||||
Generate
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Logout everywhere modal -->
|
||||
<div class="modal modal-blur" tabindex="-1" id="modal-logout-confirm">
|
||||
<div class="modal-dialog modal-sm modal-dialog-centered" role="document">
|
||||
|
|
@ -108,7 +153,8 @@
|
|||
|
||||
<div class="col">
|
||||
<form action="./security/logout_everywhere" method="post">
|
||||
<button type="submit" name="logout_everywhere" value="true" class="btn btn-danger w-100">
|
||||
<button type="submit" name="logout_everywhere" value="true"
|
||||
class="btn btn-danger w-100">
|
||||
Logout everywhere
|
||||
</button>
|
||||
</form>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue