diff --git a/Cargo.lock b/Cargo.lock index bc5ed00..e412c7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5390,6 +5390,7 @@ dependencies = [ "async-trait", "bon", "chrono", + "convert_case 0.8.0", "futures", "serde", "serde_json", diff --git a/examples/axum/src/main.rs b/examples/axum/src/main.rs index 9268751..6bf5ff7 100644 --- a/examples/axum/src/main.rs +++ b/examples/axum/src/main.rs @@ -54,7 +54,7 @@ async fn main() { let api_router = OpenApiRouter::new() .route("/protected", get(async || "Protected")) .route_layer(from_fn(auth_required::)) - .nest("/auth", AuthRoutes::openapi_router::()); + .nest("/auth", AuthRoutes::new(shield).openapi_router()); // Initialize router let (router, openapi) = OpenApiRouter::new() diff --git a/examples/leptos-axum/src/main.rs b/examples/leptos-axum/src/main.rs index 811fcfe..acb9c25 100644 --- a/examples/leptos-axum/src/main.rs +++ b/examples/leptos-axum/src/main.rs @@ -4,10 +4,7 @@ async fn main() { use std::sync::Arc; use axum::{Router, middleware::from_fn, routing::get}; - use leptos::{ - config::{LeptosOptions, get_configuration}, - context::provide_context, - }; + use leptos::{config::get_configuration, context::provide_context}; use leptos_axum::{LeptosRoutes, generate_route_list}; use shield::{Shield, ShieldOptions}; use shield_bootstrap::BootstrapLeptosStyle; @@ -62,7 +59,7 @@ async fn main() { let router = Router::new() .route("/api/protected", get(async || "Protected")) .route_layer(from_fn(auth_required::)) - .nest("/api/auth", AuthRoutes::router::()) + .nest("/api/auth", AuthRoutes::new(shield).router()) .leptos_routes_with_context( &leptos_options, routes, diff --git a/packages/core/shield/Cargo.toml b/packages/core/shield/Cargo.toml index 09bf050..40a526f 100644 --- a/packages/core/shield/Cargo.toml +++ b/packages/core/shield/Cargo.toml @@ -16,6 +16,7 @@ utoipa = ["dep:utoipa"] async-trait.workspace = true bon.workspace = true chrono = { workspace = true, features = ["serde"] } +convert_case = "0.8.0" futures.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true diff --git a/packages/core/shield/src/action.rs b/packages/core/shield/src/action.rs index f9db85b..2982470 100644 --- a/packages/core/shield/src/action.rs +++ b/packages/core/shield/src/action.rs @@ -1,8 +1,5 @@ use std::any::Any; -use async_trait::async_trait; -use serde::{Deserialize, Serialize}; - use crate::{ error::ShieldError, form::Form, @@ -11,6 +8,38 @@ use crate::{ response::Response, session::{BaseSession, MethodSession}, }; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; +#[cfg(feature = "utoipa")] +use utoipa::openapi::HttpMethod; + +#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum ActionMethod { + Get, + Post, + Put, + Delete, + Options, + Head, + Patch, + Trace, +} + +#[cfg(feature = "utoipa")] +impl From for HttpMethod { + fn from(value: ActionMethod) -> Self { + match value { + ActionMethod::Get => Self::Get, + ActionMethod::Post => Self::Post, + ActionMethod::Put => Self::Put, + ActionMethod::Delete => Self::Delete, + ActionMethod::Options => Self::Options, + ActionMethod::Head => Self::Head, + ActionMethod::Patch => Self::Patch, + ActionMethod::Trace => Self::Trace, + } + } +} // TODO: Think of a better name. #[derive(Clone, Debug, Deserialize, Serialize)] @@ -46,6 +75,12 @@ pub trait Action: ErasedAction + Send + Sync { fn name(&self) -> String; + fn openapi_summary(&self) -> &'static str; + + fn openapi_description(&self) -> &'static str; + + fn method(&self) -> ActionMethod; + fn condition(&self, _provider: &P, _session: &MethodSession) -> Result { Ok(true) } @@ -66,6 +101,12 @@ pub trait ErasedAction: Send + Sync { fn erased_name(&self) -> String; + fn erased_openapi_summary(&self) -> &'static str; + + fn erased_openapi_description(&self) -> &'static str; + + fn erased_method(&self) -> ActionMethod; + fn erased_condition( &self, provider: &(dyn Any + Send + Sync), @@ -100,6 +141,18 @@ macro_rules! erased_action { self.name() } + fn erased_openapi_summary(&self) -> &'static str { + self.openapi_summary() + } + + fn erased_openapi_description(&self) -> &'static str { + self.openapi_description() + } + + fn erased_method(&self) -> $crate::ActionMethod { + self.method() + } + fn erased_condition( &self, provider: &(dyn std::any::Any + Send + Sync), diff --git a/packages/core/shield/src/actions/sign_out.rs b/packages/core/shield/src/actions/sign_out.rs index 0f4542a..a2e46a9 100644 --- a/packages/core/shield/src/actions/sign_out.rs +++ b/packages/core/shield/src/actions/sign_out.rs @@ -3,6 +3,9 @@ use crate::{Form, Input, InputType, InputTypeSubmit, MethodSession, Provider, Sh const ACTION_ID: &str = "sign-out"; const ACTION_NAME: &str = "Sign out"; +// TODO: Sign out should be a global action that is independent of the method. +// TODO: Add hooks, so the method can still perform custom sign out. + pub struct SignOutAction; impl SignOutAction { diff --git a/packages/core/shield/src/lib.rs b/packages/core/shield/src/lib.rs index 98c505e..6302e6e 100644 --- a/packages/core/shield/src/lib.rs +++ b/packages/core/shield/src/lib.rs @@ -4,6 +4,7 @@ mod error; mod form; mod method; mod options; +mod path; mod provider; mod request; mod response; @@ -19,6 +20,7 @@ pub use error::*; pub use form::*; pub use method::*; pub use options::*; +pub use path::*; pub use provider::*; pub use request::*; pub use response::*; diff --git a/packages/integrations/shield-axum/src/path.rs b/packages/core/shield/src/path.rs similarity index 100% rename from packages/integrations/shield-axum/src/path.rs rename to packages/core/shield/src/path.rs diff --git a/packages/core/shield/src/shield.rs b/packages/core/shield/src/shield.rs index e731df3..8f85637 100644 --- a/packages/core/shield/src/shield.rs +++ b/packages/core/shield/src/shield.rs @@ -1,13 +1,24 @@ use std::{any::Any, collections::HashMap, sync::Arc}; +#[cfg(feature = "utoipa")] +use convert_case::{Case, Casing}; use futures::future::try_join_all; -use tracing::{debug, warn}; +use tracing::warn; +#[cfg(feature = "utoipa")] +use utoipa::{ + IntoParams, + openapi::{ + OpenApi, PathItem, Paths, + path::{Operation, ParameterIn}, + }, +}; use crate::{ action::{ActionForms, ActionMethodForm, ActionProviderForm}, error::{ActionError, MethodError, ProviderError, SessionError, ShieldError}, method::ErasedMethod, options::ShieldOptions, + path::ActionPathParams, request::Request, response::ResponseType, session::Session, @@ -184,16 +195,12 @@ impl Shield { .erased_call(provider, &base_session, &*method_session, request) .await?; - debug!("response {:#?}", response); - for session_action in &response.session_actions { session_action .call(method_id, provider_id, &session) .await?; } - debug!("session actions processed"); - Ok(response.r#type) } @@ -232,6 +239,49 @@ impl Shield { None => Ok(None), } } + + #[cfg(feature = "utoipa")] + pub fn openapi(&self) -> OpenApi { + let mut paths = Paths::builder(); + + for method in self.methods.values() { + for action in method.erased_actions() { + use utoipa::openapi::Response; + + let method_id = method.erased_id(); + let action_id = action.erased_id(); + + // TODO: Query, request body, responses. + + paths = paths.path( + format!("/{}/{}/{{providerId}}", method_id, action_id), + PathItem::builder() + .operation( + action.erased_method().into(), + Operation::builder() + .operation_id(Some(format!( + "{}{}", + action_id.to_case(Case::Camel), + method_id.to_case(Case::UpperCamel) + ))) + .summary(Some(action.erased_openapi_summary())) + .description(Some(action.erased_openapi_description())) + .tag("auth") + .parameters(Some(ActionPathParams::into_params(|| { + Some(ParameterIn::Path) + }))) + .response( + "500", + Response::builder().description("Internal server error."), + ), + ) + .build(), + ); + } + } + + OpenApi::builder().paths(paths.build()).build() + } } #[cfg(test)] diff --git a/packages/integrations/shield-axum/src/lib.rs b/packages/integrations/shield-axum/src/lib.rs index 41537f3..5fe88ea 100644 --- a/packages/integrations/shield-axum/src/lib.rs +++ b/packages/integrations/shield-axum/src/lib.rs @@ -1,7 +1,6 @@ mod error; mod extract; mod middleware; -mod path; mod router; mod routes; diff --git a/packages/integrations/shield-axum/src/router.rs b/packages/integrations/shield-axum/src/router.rs index eef7a6e..7499de8 100644 --- a/packages/integrations/shield-axum/src/router.rs +++ b/packages/integrations/shield-axum/src/router.rs @@ -1,32 +1,40 @@ use axum::{ Router, - routing::{get, post}, + routing::{any, get, post}, }; -use shield::User; +use shield::{Shield, User}; +#[cfg(feature = "utoipa")] use utoipa::OpenApi; +#[cfg(feature = "utoipa")] use utoipa_axum::router::OpenApiRouter; use crate::routes::*; +#[cfg(feature = "utoipa")] #[cfg_attr(feature = "utoipa", derive(utoipa::OpenApi))] #[cfg_attr(feature = "utoipa", openapi(paths(action, forms, user)))] -pub struct AuthRoutes; +struct BaseOpenApi; -impl AuthRoutes { - pub fn router() -> Router { +pub struct AuthRoutes { + shield: Shield, +} + +impl AuthRoutes { + pub fn new(shield: Shield) -> Self { + Self { shield } + } + + pub fn router(&self) -> Router { Router::new() .route("/user", get(user::)) .route("/forms/{actionId}", get(forms::)) - .route("/{methodId}/{actionId}", get(action::)) - .route("/{methodId}/{actionId}", post(action::)) - .route("/{methodId}/{actionId}/{providerId}", get(action::)) - .route("/{methodId}/{actionId}/{providerId}", post(action::)) + .route("/{methodId}/{actionId}", any(action::)) + .route("/{methodId}/{actionId}/{providerId}", any(action::)) } #[cfg(feature = "utoipa")] - pub fn openapi_router() - -> OpenApiRouter { - OpenApiRouter::with_openapi(AuthRoutes::openapi()) + pub fn openapi_router(&self) -> OpenApiRouter { + OpenApiRouter::with_openapi(BaseOpenApi::openapi().merge_from(self.shield.openapi())) .route("/user", get(user::)) .route("/forms/{actionId}", get(forms::)) .route("/{methodId}/{actionId}", get(action::)) diff --git a/packages/integrations/shield-axum/src/routes/action.rs b/packages/integrations/shield-axum/src/routes/action.rs index ecd0593..af3b0a4 100644 --- a/packages/integrations/shield-axum/src/routes/action.rs +++ b/packages/integrations/shield-axum/src/routes/action.rs @@ -4,9 +4,9 @@ use axum::{ response::{IntoResponse, Redirect, Response}, }; use serde_json::Value; -use shield::{Request, ResponseType, User}; +use shield::{ActionPathParams, Request, ResponseType, User}; -use crate::{ExtractSession, ExtractShield, RouteError, error::ErrorBody, path::ActionPathParams}; +use crate::{ExtractSession, ExtractShield, RouteError, error::ErrorBody}; #[cfg_attr( feature = "utoipa", diff --git a/packages/integrations/shield-axum/src/routes/forms.rs b/packages/integrations/shield-axum/src/routes/forms.rs index a4d05de..06f06d7 100644 --- a/packages/integrations/shield-axum/src/routes/forms.rs +++ b/packages/integrations/shield-axum/src/routes/forms.rs @@ -1,9 +1,7 @@ use axum::{Json, extract::Path}; -use shield::{ActionForms, User}; +use shield::{ActionForms, ActionFormsPathParams, User}; -use crate::{ - ExtractSession, ExtractShield, RouteError, error::ErrorBody, path::ActionFormsPathParams, -}; +use crate::{ExtractSession, ExtractShield, RouteError, error::ErrorBody}; #[cfg_attr( feature = "utoipa", diff --git a/packages/methods/shield-credentials/src/actions/sign_in.rs b/packages/methods/shield-credentials/src/actions/sign_in.rs index ca0967a..7d5339a 100644 --- a/packages/methods/shield-credentials/src/actions/sign_in.rs +++ b/packages/methods/shield-credentials/src/actions/sign_in.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use async_trait::async_trait; use serde::de::DeserializeOwned; use shield::{ - Action, Form, MethodSession, Request, Response, ResponseType, SessionAction, ShieldError, - SignInAction, User, erased_action, + Action, ActionMethod, Form, MethodSession, Request, Response, ResponseType, SessionAction, + ShieldError, SignInAction, User, erased_action, }; use crate::{credentials::Credentials, provider::CredentialsProvider}; @@ -31,6 +31,18 @@ impl Action &'static str { + "Sign in with credentials" + } + + fn openapi_description(&self) -> &'static str { + "Sign in with credentials." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + async fn forms(&self, _provider: CredentialsProvider) -> Result, ShieldError> { Ok(vec![self.credentials.form()]) } diff --git a/packages/methods/shield-credentials/src/actions/sign_out.rs b/packages/methods/shield-credentials/src/actions/sign_out.rs index db5c7b5..a0b9dd3 100644 --- a/packages/methods/shield-credentials/src/actions/sign_out.rs +++ b/packages/methods/shield-credentials/src/actions/sign_out.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use shield::{ - Action, Form, MethodSession, Request, Response, ResponseType, SessionAction, ShieldError, - SignOutAction, erased_action, + Action, ActionMethod, Form, MethodSession, Request, Response, ResponseType, SessionAction, + ShieldError, SignOutAction, erased_action, }; use crate::provider::CredentialsProvider; @@ -18,6 +18,18 @@ impl Action for CredentialsSignOutAction { SignOutAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign out with credentials" + } + + fn openapi_description(&self) -> &'static str { + "Sign out with credentials." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + fn condition( &self, provider: &CredentialsProvider, diff --git a/packages/methods/shield-oauth/src/actions/sign_in.rs b/packages/methods/shield-oauth/src/actions/sign_in.rs index 75fa84c..2e3719a 100644 --- a/packages/methods/shield-oauth/src/actions/sign_in.rs +++ b/packages/methods/shield-oauth/src/actions/sign_in.rs @@ -1,8 +1,9 @@ use async_trait::async_trait; use oauth2::{CsrfToken, PkceCodeChallenge, Scope, url::form_urlencoded::parse}; use shield::{ - Action, ConfigurationError, Form, Input, InputType, InputTypeSubmit, MethodSession, Provider, - Request, Response, ResponseType, SessionAction, ShieldError, SignInAction, erased_action, + Action, ActionMethod, ConfigurationError, Form, Input, InputType, InputTypeSubmit, + MethodSession, Provider, Request, Response, ResponseType, SessionAction, ShieldError, + SignInAction, erased_action, }; use crate::{ @@ -22,6 +23,18 @@ impl Action for OauthSignInAction { SignInAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign in with OAuth" + } + + fn openapi_description(&self) -> &'static str { + "Sign in with OAuth." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + async fn forms(&self, provider: OauthProvider) -> Result, ShieldError> { Ok(vec![Form { inputs: vec![Input { diff --git a/packages/methods/shield-oauth/src/actions/sign_in_callback.rs b/packages/methods/shield-oauth/src/actions/sign_in_callback.rs index a5a1baa..20a0617 100644 --- a/packages/methods/shield-oauth/src/actions/sign_in_callback.rs +++ b/packages/methods/shield-oauth/src/actions/sign_in_callback.rs @@ -8,9 +8,9 @@ use oauth2::{ }; use secrecy::SecretString; use shield::{ - Action, ConfigurationError, CreateEmailAddress, CreateUser, Form, MethodSession, Request, - Response, ResponseType, SessionAction, ShieldError, SignInCallbackAction, UpdateUser, User, - erased_action, + Action, ActionMethod, ConfigurationError, CreateEmailAddress, CreateUser, Form, MethodSession, + Request, Response, ResponseType, SessionAction, ShieldError, SignInCallbackAction, UpdateUser, + User, erased_action, }; use crate::{ @@ -138,6 +138,18 @@ impl Action for OauthSignInCallb SignInCallbackAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign in callback for OAuth" + } + + fn openapi_description(&self) -> &'static str { + "Sign in callback for OAuth." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Get + } + fn condition( &self, provider: &OauthProvider, diff --git a/packages/methods/shield-oauth/src/actions/sign_out.rs b/packages/methods/shield-oauth/src/actions/sign_out.rs index 075e0ac..eceb75a 100644 --- a/packages/methods/shield-oauth/src/actions/sign_out.rs +++ b/packages/methods/shield-oauth/src/actions/sign_out.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use shield::{ - Action, Form, MethodSession, Request, Response, ResponseType, SessionAction, ShieldError, - SignOutAction, erased_action, + Action, ActionMethod, Form, MethodSession, Request, Response, ResponseType, SessionAction, + ShieldError, SignOutAction, erased_action, }; use crate::{provider::OauthProvider, session::OauthSession}; @@ -18,6 +18,18 @@ impl Action for OauthSignOutAction { SignOutAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign out with OAuth" + } + + fn openapi_description(&self) -> &'static str { + "Sign out with OAuth." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + fn condition( &self, provider: &OauthProvider, diff --git a/packages/methods/shield-oidc/src/actions/sign_in.rs b/packages/methods/shield-oidc/src/actions/sign_in.rs index c767662..9e3089d 100644 --- a/packages/methods/shield-oidc/src/actions/sign_in.rs +++ b/packages/methods/shield-oidc/src/actions/sign_in.rs @@ -4,8 +4,8 @@ use openidconnect::{ url::form_urlencoded::parse, }; use shield::{ - Action, Form, Input, InputType, InputTypeSubmit, MethodSession, Provider, Request, Response, - ResponseType, SessionAction, ShieldError, SignInAction, erased_action, + Action, ActionMethod, Form, Input, InputType, InputTypeSubmit, MethodSession, Provider, + Request, Response, ResponseType, SessionAction, ShieldError, SignInAction, erased_action, }; use crate::{ @@ -25,6 +25,18 @@ impl Action for OidcSignInAction { SignInAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign in with OpenID Connect" + } + + fn openapi_description(&self) -> &'static str { + "Sign in with OpenID Connect." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + async fn forms(&self, provider: OidcProvider) -> Result, ShieldError> { Ok(vec![Form { inputs: vec![Input { diff --git a/packages/methods/shield-oidc/src/actions/sign_in_callback.rs b/packages/methods/shield-oidc/src/actions/sign_in_callback.rs index b6e4eca..ae70c28 100644 --- a/packages/methods/shield-oidc/src/actions/sign_in_callback.rs +++ b/packages/methods/shield-oidc/src/actions/sign_in_callback.rs @@ -10,9 +10,9 @@ use openidconnect::{ }; use secrecy::SecretString; use shield::{ - Action, ConfigurationError, CreateEmailAddress, CreateUser, Form, MethodSession, Request, - Response, ResponseType, SessionAction, ShieldError, SignInCallbackAction, UpdateUser, User, - erased_action, + Action, ActionMethod, ConfigurationError, CreateEmailAddress, CreateUser, Form, MethodSession, + Request, Response, ResponseType, SessionAction, ShieldError, SignInCallbackAction, UpdateUser, + User, erased_action, }; use tracing::debug; @@ -149,6 +149,18 @@ impl Action for OidcSignInCallback SignInCallbackAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign in callback for OpenID Connect" + } + + fn openapi_description(&self) -> &'static str { + "Sign in callback for OpenID Connect." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Get + } + fn condition( &self, provider: &OidcProvider, diff --git a/packages/methods/shield-oidc/src/actions/sign_out.rs b/packages/methods/shield-oidc/src/actions/sign_out.rs index 9feabe5..ecb6d4b 100644 --- a/packages/methods/shield-oidc/src/actions/sign_out.rs +++ b/packages/methods/shield-oidc/src/actions/sign_out.rs @@ -1,7 +1,7 @@ use async_trait::async_trait; use shield::{ - Action, Form, MethodSession, Request, Response, ResponseType, SessionAction, ShieldError, - SignOutAction, erased_action, + Action, ActionMethod, Form, MethodSession, Request, Response, ResponseType, SessionAction, + ShieldError, SignOutAction, erased_action, }; use crate::{provider::OidcProvider, session::OidcSession}; @@ -18,6 +18,18 @@ impl Action for OidcSignOutAction { SignOutAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign out with OpenID Connect" + } + + fn openapi_description(&self) -> &'static str { + "Sign out with OpenID Connect." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + fn condition( &self, provider: &OidcProvider, diff --git a/packages/methods/shield-workos/src/actions/index.rs b/packages/methods/shield-workos/src/actions/index.rs index f673c1c..fed5440 100644 --- a/packages/methods/shield-workos/src/actions/index.rs +++ b/packages/methods/shield-workos/src/actions/index.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use async_trait::async_trait; use serde::Deserialize; use shield::{ - Action, Form, Input, InputType, InputTypeEmail, InputTypeHidden, InputTypeSubmit, + Action, ActionMethod, Form, Input, InputType, InputTypeEmail, InputTypeHidden, InputTypeSubmit, MethodSession, Request, Response, ResponseType, ShieldError, SignInAction, SignUpAction, erased_action, }; @@ -50,6 +50,18 @@ impl Action for WorkosIndexAction { ACTION_NAME.to_owned() } + fn openapi_summary(&self) -> &'static str { + "Index with WorkOS" + } + + fn openapi_description(&self) -> &'static str { + "Index with WorkOS." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + async fn forms(&self, _provider: WorkosProvider) -> Result, ShieldError> { let connections = self .client diff --git a/packages/methods/shield-workos/src/actions/sign_in.rs b/packages/methods/shield-workos/src/actions/sign_in.rs index 0c618a3..6f4a21c 100644 --- a/packages/methods/shield-workos/src/actions/sign_in.rs +++ b/packages/methods/shield-workos/src/actions/sign_in.rs @@ -2,9 +2,9 @@ use std::sync::Arc; use async_trait::async_trait; use shield::{ - Action, Form, Input, InputType, InputTypeEmail, InputTypeHidden, InputTypePassword, - InputTypeSubmit, MethodSession, Request, Response, ResponseType, ShieldError, SignInAction, - erased_action, + Action, ActionMethod, Form, Input, InputType, InputTypeEmail, InputTypeHidden, + InputTypePassword, InputTypeSubmit, MethodSession, Request, Response, ResponseType, + ShieldError, SignInAction, erased_action, }; use crate::{client::WorkosClient, provider::WorkosProvider}; @@ -31,6 +31,18 @@ impl Action for WorkosSignInAction { SignInAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign in with WorkOS" + } + + fn openapi_description(&self) -> &'static str { + "Sign in with WorkOS." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + async fn forms(&self, _provider: WorkosProvider) -> Result, ShieldError> { // TODO: Magic auth and SSO buttons. // TODO: Prefill email address. diff --git a/packages/methods/shield-workos/src/actions/sign_out.rs b/packages/methods/shield-workos/src/actions/sign_out.rs index a06d889..383fc3f 100644 --- a/packages/methods/shield-workos/src/actions/sign_out.rs +++ b/packages/methods/shield-workos/src/actions/sign_out.rs @@ -2,8 +2,8 @@ use std::sync::Arc; use async_trait::async_trait; use shield::{ - Action, Form, MethodSession, Request, Response, ResponseType, SessionAction, ShieldError, - SignOutAction, erased_action, + Action, ActionMethod, Form, MethodSession, Request, Response, ResponseType, SessionAction, + ShieldError, SignOutAction, erased_action, }; use crate::{client::WorkosClient, provider::WorkosProvider}; @@ -30,6 +30,18 @@ impl Action for WorkosSignOutAction { SignOutAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign out with WorkOS" + } + + fn openapi_description(&self) -> &'static str { + "Sign out with WorkOS." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + fn condition( &self, provider: &WorkosProvider, diff --git a/packages/methods/shield-workos/src/actions/sign_up.rs b/packages/methods/shield-workos/src/actions/sign_up.rs index ee19f1c..b91f9b7 100644 --- a/packages/methods/shield-workos/src/actions/sign_up.rs +++ b/packages/methods/shield-workos/src/actions/sign_up.rs @@ -2,9 +2,9 @@ use std::sync::Arc; use async_trait::async_trait; use shield::{ - Action, Form, Input, InputType, InputTypeEmail, InputTypeHidden, InputTypePassword, - InputTypeSubmit, MethodSession, Request, Response, ResponseType, ShieldError, SignUpAction, - erased_action, + Action, ActionMethod, Form, Input, InputType, InputTypeEmail, InputTypeHidden, + InputTypePassword, InputTypeSubmit, MethodSession, Request, Response, ResponseType, + ShieldError, SignUpAction, erased_action, }; use crate::{client::WorkosClient, provider::WorkosProvider}; @@ -31,6 +31,18 @@ impl Action for WorkosSignUpAction { SignUpAction::name() } + fn openapi_summary(&self) -> &'static str { + "Sign up with WorkOS" + } + + fn openapi_description(&self) -> &'static str { + "Sign up with WorkOS." + } + + fn method(&self) -> ActionMethod { + ActionMethod::Post + } + async fn forms(&self, _provider: WorkosProvider) -> Result, ShieldError> { // TODO: Magic auth and SSO buttons. // TODO: Prefill email address.