Skip to main content

openauth_cli/
plugins.rs

1use openauth_core::db::DbSchema;
2use openauth_core::db::MemoryAdapter;
3use openauth_core::error::OpenAuthError;
4use openauth_core::plugin::AuthPlugin;
5use openauth_plugins::{
6    admin::{admin, AdminOptions},
7    anonymous::{anonymous, AnonymousOptions},
8    api_key::api_key,
9    device_authorization::device_authorization,
10    jwt::jwt,
11    mcp::{mcp, McpOptions},
12    organization::organization,
13    phone_number::{phone_number, PhoneNumberOptions},
14    siwe::{siwe, SiweOptions},
15    two_factor::{two_factor, TwoFactorOptions},
16    username::username,
17    PLUGIN_IDS,
18};
19use serde::Serialize;
20use std::sync::Arc;
21
22#[derive(Debug, Clone, Serialize)]
23pub struct PluginInfo {
24    pub id: &'static str,
25    pub official: bool,
26    pub schema_supported: bool,
27    pub snippet_supported: bool,
28    pub migration_impact: bool,
29}
30
31pub fn official_plugins() -> Vec<PluginInfo> {
32    PLUGIN_IDS
33        .iter()
34        .map(|id| PluginInfo {
35            id,
36            official: true,
37            schema_supported: schema_plugin(id).is_some(),
38            snippet_supported: rust_snippet(id).is_some(),
39            migration_impact: schema_plugin(id).is_some(),
40        })
41        .collect()
42}
43
44pub fn is_official_plugin(plugin: &str) -> bool {
45    PLUGIN_IDS.contains(&plugin)
46}
47
48pub fn apply_configured_plugins(
49    schema: &mut DbSchema,
50    plugins: &[String],
51) -> Result<(), OpenAuthError> {
52    for plugin in plugins {
53        let Some(auth_plugin) = schema_plugin(plugin) else {
54            continue;
55        };
56        for contribution in auth_plugin.schema {
57            contribution.apply(schema)?;
58        }
59    }
60    Ok(())
61}
62
63pub fn schema_plugin(plugin: &str) -> Option<AuthPlugin> {
64    match plugin {
65        "admin" => Some(admin(AdminOptions::default())),
66        "anonymous" => Some(anonymous(AnonymousOptions::default())),
67        "api-key" => Some(api_key()),
68        "device-authorization" => Some(device_authorization()),
69        "jwt" => jwt().ok(),
70        "mcp" => mcp(McpOptions {
71            login_page: "/login".to_owned(),
72            ..McpOptions::default()
73        })
74        .ok()
75        .map(|plugin| plugin.into_auth_plugin()),
76        "organization" => Some(organization()),
77        "phone-number" => Some(phone_number(
78            Arc::new(MemoryAdapter::new()),
79            PhoneNumberOptions::default(),
80        )),
81        "siwe" => siwe(SiweOptions::new(
82            "localhost",
83            || async { Ok("nonce".to_owned()) },
84            |_| async { Ok(true) },
85        ))
86        .ok(),
87        "two-factor" => Some(two_factor(TwoFactorOptions::default())),
88        "username" => Some(username()),
89        _ => None,
90    }
91}
92
93pub fn rust_snippet(plugin: &str) -> Option<&'static str> {
94    match plugin {
95        "two-factor" => {
96            Some("openauth::plugins::two_factor::two_factor(TwoFactorOptions::default())")
97        }
98        "organization" => Some("openauth::plugins::organization::organization()"),
99        "username" => Some("openauth::plugins::username::username()"),
100        "admin" => Some("openauth::plugins::admin::admin(AdminOptions::default())"),
101        "api-key" => Some("openauth::plugins::api_key::api_key()"),
102        "device-authorization" => {
103            Some("openauth::plugins::device_authorization::device_authorization()")
104        }
105        "anonymous" => Some("openauth::plugins::anonymous::anonymous(AnonymousOptions::default())"),
106        "jwt" => Some("openauth::plugins::jwt::jwt()?"),
107        _ => None,
108    }
109}