feat(auth): add WebAuthn passkey support with migrations, routes, and tests
This commit is contained in:
@@ -11,7 +11,7 @@ use axum::Router;
|
||||
use backend::auth::jwt::JwtService;
|
||||
use backend::config::AppConfig;
|
||||
use backend::db::{self, PgPool};
|
||||
use backend::models::{Job, NewUser, NewUserMembership, Tenant, TenantStatus};
|
||||
use backend::models::{Job, NewUser, NewUserMembership, NewUserPasskey, Tenant, TenantStatus};
|
||||
use backend::routes;
|
||||
use backend::state::AppState;
|
||||
use backend::storage::ObjectStorage;
|
||||
@@ -24,7 +24,7 @@ use http_body_util::BodyExt;
|
||||
use once_cell::sync::Lazy;
|
||||
use rand::rngs::OsRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json;
|
||||
use serde_json::{self, json};
|
||||
use tokio::sync::Mutex;
|
||||
use tower::util::ServiceExt;
|
||||
use uuid::Uuid;
|
||||
@@ -142,6 +142,9 @@ impl TestApp {
|
||||
quickwit_index: None,
|
||||
default_tenant_slug: "admin".to_string(),
|
||||
worker_max_document_bytes: 200 * 1024 * 1024,
|
||||
webauthn_rp_id: Some("localhost".to_string()),
|
||||
webauthn_origin: Some("http://localhost".to_string()),
|
||||
webauthn_rp_name: "Papercrate".to_string(),
|
||||
};
|
||||
|
||||
let pool = db::init_pool_with_size(&config.database_url, config.database_max_pool_size)?;
|
||||
@@ -199,10 +202,9 @@ impl TestApp {
|
||||
Ok(format!("{}{}", root, key))
|
||||
}
|
||||
|
||||
pub async fn insert_user(&self, username: &str, password: &str, role: &str) -> Result<Uuid> {
|
||||
pub async fn insert_user(&self, username: &str, password: &str, _role: &str) -> Result<Uuid> {
|
||||
let username = username.to_string();
|
||||
let password = password.to_string();
|
||||
let role = role.to_string();
|
||||
let tenant_id = self
|
||||
.state
|
||||
.tenants
|
||||
@@ -224,7 +226,6 @@ impl TestApp {
|
||||
id: Uuid::new_v4(),
|
||||
user_id: user.id,
|
||||
tenant_id,
|
||||
role,
|
||||
};
|
||||
|
||||
diesel::insert_into(backend::schema::user_memberships::table)
|
||||
@@ -236,6 +237,32 @@ impl TestApp {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn insert_passkey(&self, user_id: Uuid, nickname: Option<&str>) -> Result<Uuid> {
|
||||
let passkey_id = Uuid::new_v4();
|
||||
let nickname = nickname.map(|value| value.to_string());
|
||||
self.with_conn(move |conn| {
|
||||
let passkey = NewUserPasskey {
|
||||
id: passkey_id,
|
||||
user_id,
|
||||
credential_id: vec![1, 2, 3],
|
||||
public_key: vec![4, 5, 6],
|
||||
credential: json!({ "dummy": true }),
|
||||
sign_count: 0,
|
||||
transports: vec![Some("usb".to_string())],
|
||||
aaguid: None,
|
||||
nickname,
|
||||
};
|
||||
|
||||
diesel::insert_into(backend::schema::user_passkeys::table)
|
||||
.values(&passkey)
|
||||
.execute(conn)
|
||||
.context("failed to insert passkey")?;
|
||||
|
||||
Ok(passkey_id)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn ensure_default_tenant(&self) -> Result<Uuid> {
|
||||
let slug_value = self.state.config.default_tenant_slug.clone();
|
||||
let quickwit_enabled = self.state.config.quickwit_endpoint.is_some();
|
||||
|
||||
Reference in New Issue
Block a user