snapshot of https://github.com/tauri-apps/plugins-workspace.git (v2, 2026-09-23; blobs > 131072B omitted)
Some checks failed
integration tests / run-integration-tests (windows-latest) (push) Has been cancelled
Test Rust / test (push) Has been cancelled
test plugins e2e (mobile) / ios (push) Has been cancelled
test plugins e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test plugins e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
integration tests / run-integration-tests (macos-latest) (push) Has been cancelled
version or publish / version-or-publish (push) Failing after 0s
integration tests / run-integration-tests (ubuntu-22.04) (push) Failing after 0s
Lint JavaScript / eslint (push) Failing after 0s
Sync / sync-to-mirrors (push) Failing after 0s
test plugins e2e (mobile) / android (push) Failing after 0s
test plugins e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
Test Rust / changes (push) Failing after 0s
Lint Rust / changes (push) Failing after 0s
Lint Rust / clippy (push) Has been skipped
Audit Rust / audit-rust (push) Failing after 1s
Audit JavaScript / audit-js (push) Failing after 1s
Some checks failed
integration tests / run-integration-tests (windows-latest) (push) Has been cancelled
Test Rust / test (push) Has been cancelled
test plugins e2e (mobile) / ios (push) Has been cancelled
test plugins e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test plugins e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
integration tests / run-integration-tests (macos-latest) (push) Has been cancelled
version or publish / version-or-publish (push) Failing after 0s
integration tests / run-integration-tests (ubuntu-22.04) (push) Failing after 0s
Lint JavaScript / eslint (push) Failing after 0s
Sync / sync-to-mirrors (push) Failing after 0s
test plugins e2e (mobile) / android (push) Failing after 0s
test plugins e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
Test Rust / changes (push) Failing after 0s
Lint Rust / changes (push) Failing after 0s
Lint Rust / clippy (push) Has been skipped
Audit Rust / audit-rust (push) Failing after 1s
Audit JavaScript / audit-js (push) Failing after 1s
This commit is contained in:
31
plugins/biometric/src/error.rs
Normal file
31
plugins/biometric/src/error.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::{ser::Serializer, Serialize};
|
||||
|
||||
/// Alias for a [`Result`](std::result::Result) with the error type [`Error`].
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// The error types returned by this plugin.
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
/// An I/O error occurred.
|
||||
#[error(transparent)]
|
||||
Io(#[from] std::io::Error),
|
||||
/// The invocation of the underlying Android or iOS plugin failed, for example because
|
||||
/// biometric authentication was unavailable, was not enrolled, failed, or was canceled by
|
||||
/// the user.
|
||||
#[cfg(mobile)]
|
||||
#[error(transparent)]
|
||||
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
|
||||
}
|
||||
|
||||
impl Serialize for Error {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.to_string().as_ref())
|
||||
}
|
||||
}
|
||||
82
plugins/biometric/src/lib.rs
Normal file
82
plugins/biometric/src/lib.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//! Prompt the user for biometric authentication.
|
||||
//!
|
||||
//! - Supported platforms: Android and iOS.
|
||||
|
||||
#![cfg(mobile)]
|
||||
|
||||
use serde::Serialize;
|
||||
use tauri::{
|
||||
plugin::{Builder, PluginHandle, TauriPlugin},
|
||||
Manager, Runtime,
|
||||
};
|
||||
|
||||
pub use models::*;
|
||||
|
||||
mod error;
|
||||
mod models;
|
||||
|
||||
pub use error::{Error, Result};
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
const PLUGIN_IDENTIFIER: &str = "app.tauri.biometric";
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
tauri::ios_plugin_binding!(init_plugin_biometric);
|
||||
|
||||
/// Access to the biometric APIs.
|
||||
pub struct Biometric<R: Runtime>(PluginHandle<R>);
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct AuthenticatePayload {
|
||||
reason: String,
|
||||
#[serde(flatten)]
|
||||
options: AuthOptions,
|
||||
}
|
||||
|
||||
impl<R: Runtime> Biometric<R> {
|
||||
/// Checks the device's availability and type of biometric authentication, as reported by the
|
||||
/// operating system. Errors if the underlying mobile plugin invocation fails.
|
||||
pub fn status(&self) -> crate::Result<Status> {
|
||||
self.0.run_mobile_plugin("status", ()).map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Prompts the user for biometric authentication using the system UI (Android
|
||||
/// `BiometricPrompt` or iOS `LocalAuthentication`), showing `reason` as the purpose of the
|
||||
/// request. Resolves once the user is authenticated and errors if authentication fails, is
|
||||
/// canceled, or the underlying mobile plugin invocation fails.
|
||||
pub fn authenticate(&self, reason: String, options: AuthOptions) -> crate::Result<()> {
|
||||
self.0
|
||||
.run_mobile_plugin("authenticate", AuthenticatePayload { reason, options })
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the biometric APIs.
|
||||
pub trait BiometricExt<R: Runtime> {
|
||||
/// Returns the [`Biometric`] instance managed by the app.
|
||||
fn biometric(&self) -> &Biometric<R>;
|
||||
}
|
||||
|
||||
impl<R: Runtime, T: Manager<R>> crate::BiometricExt<R> for T {
|
||||
fn biometric(&self) -> &Biometric<R> {
|
||||
self.state::<Biometric<R>>().inner()
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the plugin.
|
||||
pub fn init<R: Runtime>() -> TauriPlugin<R> {
|
||||
Builder::new("biometric")
|
||||
.setup(|app, api| {
|
||||
#[cfg(target_os = "android")]
|
||||
let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "BiometricPlugin")?;
|
||||
#[cfg(target_os = "ios")]
|
||||
let handle = api.register_ios_plugin(init_plugin_biometric)?;
|
||||
app.manage(Biometric(handle));
|
||||
Ok(())
|
||||
})
|
||||
.build()
|
||||
}
|
||||
52
plugins/biometric/src/models.rs
Normal file
52
plugins/biometric/src/models.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Options for [`Biometric::authenticate`](crate::Biometric::authenticate).
|
||||
#[derive(Debug, Default, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AuthOptions {
|
||||
/// Enables authentication using the device's password. This feature is available on both Android and iOS.
|
||||
pub allow_device_credential: bool,
|
||||
/// Label for the Cancel button. This feature is available on both Android and iOS.
|
||||
pub cancel_title: Option<String>,
|
||||
/// Specifies the text displayed on the fallback button if biometric authentication fails. This feature is available iOS only.
|
||||
pub fallback_title: Option<String>,
|
||||
/// Title indicating the purpose of biometric verification. This feature is available Android only.
|
||||
pub title: Option<String>,
|
||||
/// SubTitle providing contextual information of biometric verification. This feature is available Android only.
|
||||
pub subtitle: Option<String>,
|
||||
/// Specifies whether additional user confirmation is required, such as pressing a button after successful biometric authentication. This feature is available Android only.
|
||||
pub confirmation_required: Option<bool>,
|
||||
}
|
||||
|
||||
/// The kind of biometry hardware detected on the device.
|
||||
#[derive(Debug, Clone, serde_repr::Deserialize_repr)]
|
||||
#[repr(u8)]
|
||||
pub enum BiometryType {
|
||||
/// No biometry hardware is available, or it is not enrolled with the operating system.
|
||||
None = 0,
|
||||
/// Fingerprint authentication (Apple Touch ID or Android fingerprint).
|
||||
TouchID = 1,
|
||||
/// Face authentication (Apple Face ID or Android face authentication).
|
||||
FaceID = 2,
|
||||
}
|
||||
|
||||
/// The result of [`Biometric::status`](crate::Biometric::status), describing whether biometric
|
||||
/// authentication can currently be used.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Status {
|
||||
/// Whether the device can currently authenticate using biometrics.
|
||||
pub is_available: bool,
|
||||
/// The kind of biometry hardware detected on the device, even when [`Self::is_available`] is `false`.
|
||||
pub biometry_type: BiometryType,
|
||||
/// A human-readable reason why biometric authentication is unavailable. Only set when
|
||||
/// [`Self::is_available`] is `false`.
|
||||
pub error: Option<String>,
|
||||
/// A platform-specific error code describing why biometric authentication is unavailable.
|
||||
/// Only set when [`Self::is_available`] is `false`.
|
||||
pub error_code: Option<String>,
|
||||
}
|
||||
Reference in New Issue
Block a user