rustauth-passkey 0.3.0

Server-side passkey plugin for RustAuth.
Documentation
use indexmap::IndexMap;
use rustauth_core::db::{DbField, DbFieldType, DbTable, ForeignKey, OnDelete};
use rustauth_core::plugin::PluginSchemaContribution;

use crate::options::PasskeyOptions;

pub fn contributions(options: &PasskeyOptions) -> Vec<PluginSchemaContribution> {
    vec![PluginSchemaContribution::table(
        "passkey",
        passkey_table(options),
    )]
}

fn passkey_table(options: &PasskeyOptions) -> DbTable {
    let mut fields = IndexMap::new();
    fields.insert("id".to_owned(), DbField::new("id", DbFieldType::String));
    fields.insert(
        "name".to_owned(),
        field(options, "name", DbFieldType::String).optional(),
    );
    fields.insert(
        "public_key".to_owned(),
        field(options, "public_key", DbFieldType::String),
    );
    fields.insert(
        "user_id".to_owned(),
        field(options, "user_id", DbFieldType::String)
            .indexed()
            .references(ForeignKey::new("users", "id", OnDelete::Cascade)),
    );
    fields.insert(
        "credential_id".to_owned(),
        field(options, "credential_id", DbFieldType::String)
            .indexed()
            .unique(),
    );
    fields.insert(
        "counter".to_owned(),
        field(options, "counter", DbFieldType::Number),
    );
    fields.insert(
        "device_type".to_owned(),
        field(options, "device_type", DbFieldType::String),
    );
    fields.insert(
        "backed_up".to_owned(),
        field(options, "backed_up", DbFieldType::Boolean),
    );
    fields.insert(
        "transports".to_owned(),
        field(options, "transports", DbFieldType::String).optional(),
    );
    fields.insert(
        "created_at".to_owned(),
        field(options, "created_at", DbFieldType::Timestamp)
            .optional()
            .generated(),
    );
    fields.insert(
        "aaguid".to_owned(),
        field(options, "aaguid", DbFieldType::String).optional(),
    );
    fields.insert(
        "webauthn_credential".to_owned(),
        field(options, "webauthn_credential", DbFieldType::Json).hidden(),
    );

    DbTable {
        name: options
            .schema
            .table_name_or(&options.passkey_table)
            .to_owned(),
        fields,
        order: Some(20),
    }
}

fn field(options: &PasskeyOptions, logical_name: &str, field_type: DbFieldType) -> DbField {
    DbField::new(
        options.schema.field_name_or(logical_name, logical_name),
        field_type,
    )
}