Browse Source

Add support for passkeys in admin and user interfaces

* **Admin Interface:**
  - Add a column for passkeys in the user table in `users.hbs`.
  - Add a section for managing passkeys in `settings.hbs`.

* **Public API:**
  - Add endpoints for saving and retrieving passkeys in `public.rs`.

* **User Interface:**
  - Add a passkey input field in the login form in `login.hbs`.
pull/5490/head
Luca Cassano 2 months ago
parent
commit
c1cc9527dd
  1. 34
      src/api/core/public.rs
  2. 14
      src/static/templates/admin/settings.hbs
  3. 4
      src/static/templates/admin/users.hbs
  4. 34
      src/static/templates/user/login.hbs

34
src/api/core/public.rs

@ -15,7 +15,7 @@ use crate::{
};
pub fn routes() -> Vec<Route> {
routes![ldap_import]
routes![ldap_import, save_passkey, get_passkeys]
}
#[derive(Deserialize)]
@ -190,6 +190,38 @@ async fn ldap_import(data: Json<OrgImportData>, token: PublicToken, mut conn: Db
Ok(())
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct PasskeyData {
site: String,
passkey: String,
}
#[post("/public/passkey/save", data = "<data>")]
async fn save_passkey(data: Json<PasskeyData>, headers: Headers, mut conn: DbConn) -> EmptyResult {
let data = data.into_inner();
let user_id = headers.user.uuid;
let mut passkey = Passkey::new(user_id.clone(), data.site.clone(), data.passkey.clone());
passkey.save(&mut conn).await?;
Ok(())
}
#[get("/public/passkeys")]
async fn get_passkeys(headers: Headers, mut conn: DbConn) -> JsonResult {
let user_id = headers.user.uuid;
let passkeys = Passkey::find_by_user(&user_id, &mut conn).await;
let passkeys_json: Vec<Value> = passkeys.iter().map(|p| p.to_json()).collect();
Ok(Json(json!({
"data": passkeys_json,
"object": "list",
"continuationToken": null
})))
}
pub struct PublicToken(OrganizationId);
#[rocket::async_trait]

14
src/static/templates/admin/settings.hbs

@ -135,6 +135,20 @@
</div>
{{/if}}
<div class="card mb-3">
<button id="b_passkeys" type="button" class="card-header text-start btn btn-link text-decoration-none" aria-expanded="false" aria-controls="g_passkeys"
data-bs-toggle="collapse" data-bs-target="#g_passkeys">Manage Passkeys</button>
<div id="g_passkeys" class="card-body collapse">
<div class="small mb-3">
Here you can manage the passkeys stored in the system.
</div>
<button type="button" class="btn btn-primary" id="addPasskey">Add Passkey</button>
<div id="passkeys-list" class="mt-3">
<!-- Passkeys will be listed here -->
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-danger float-end" id="deleteConf">Reset defaults</button>
</form>

4
src/static/templates/admin/users.hbs

@ -10,6 +10,7 @@
<th class="vw-last-active">Last Active</th>
<th class="vw-entries">Entries</th>
<th class="vw-attachments">Attachments</th>
<th class="vw-passkeys">Passkeys</th>
<th class="vw-organizations">Organizations</th>
<th class="vw-actions">Actions</th>
</tr>
@ -53,6 +54,9 @@
<span class="d-block"><strong>Size:</strong> {{attachment_size}}</span>
{{/if}}
</td>
<td>
<span class="d-block">{{passkey_count}}</span>
</td>
<td>
<div class="overflow-auto vw-org-cell" data-vw-user-email="{{email}}" data-vw-user-uuid="{{id}}">
{{#each organizations}}

34
src/static/templates/user/login.hbs

@ -0,0 +1,34 @@
<main class="container-xl">
<div id="login-block" class="my-3 p-3 rounded shadow">
<h6 class="border-bottom pb-2 mb-3">User Login</h6>
<form id="login-form">
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" placeholder="Enter email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" placeholder="Enter password" required>
</div>
<div class="mb-3">
<label for="passkey" class="form-label">Passkey</label>
<input type="text" class="form-control" id="passkey" placeholder="Enter passkey">
</div>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</main>
<script>
document.getElementById('login-form').addEventListener('submit', function(event) {
event.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
const passkey = document.getElementById('passkey').value;
// Add logic to handle login with passkey
console.log('Email:', email);
console.log('Password:', password);
console.log('Passkey:', passkey);
});
</script>
Loading…
Cancel
Save