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}