mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2025-04-01 02:42:49 -05:00
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`.
This commit is contained in:
parent
2bec0ff2fd
commit
c1cc9527dd
4 changed files with 85 additions and 1 deletions
|
@ -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]
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
Normal file
34
src/static/templates/user/login.hbs
Normal file
|
@ -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…
Add table
Reference in a new issue