Skip to main content

shield/
action.rs

1use std::any::Any;
2
3use crate::{
4    error::ShieldError,
5    form::Form,
6    provider::Provider,
7    request::{Request, RequestMethod},
8    response::Response,
9    session::{BaseSession, MethodSession},
10};
11use async_trait::async_trait;
12use serde::{Deserialize, Serialize};
13
14#[async_trait]
15pub trait Action: Send + Sync {
16    fn id(&self) -> &'static str;
17
18    fn name(&self) -> &'static str;
19
20    fn openapi_summary(&self) -> &'static str;
21
22    fn openapi_description(&self) -> &'static str;
23
24    fn method(&self) -> RequestMethod;
25
26    async fn forms(&self) -> Result<Vec<Form>, ShieldError>;
27
28    async fn call(&self, session: &BaseSession, request: Request) -> Result<Response, ShieldError>;
29}
30
31// TODO: Think of a better name.
32#[derive(Clone, Debug, Deserialize, Serialize)]
33#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
34#[serde(rename_all = "camelCase")]
35pub struct ActionForms {
36    pub id: String,
37    pub name: String,
38    pub forms: Vec<Form>,
39    pub method_forms: Vec<ActionMethodForm>,
40}
41
42// TODO: Think of a better name.
43#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
44#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
45#[serde(rename_all = "camelCase")]
46pub struct ActionMethodForm {
47    pub id: String,
48    pub provider_forms: Vec<ActionProviderForm>,
49}
50
51// TODO: Think of a better name.
52#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
53#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
54#[serde(rename_all = "camelCase")]
55pub struct ActionProviderForm {
56    pub id: Option<String>,
57    pub form: Form,
58}
59
60#[async_trait]
61pub trait MethodAction<P: Provider, S>: ErasedMethodAction + Send + Sync {
62    fn id(&self) -> String;
63
64    fn name(&self) -> String;
65
66    fn openapi_summary(&self) -> &'static str;
67
68    fn openapi_description(&self) -> &'static str;
69
70    fn method(&self) -> RequestMethod;
71
72    fn condition(&self, _provider: &P, _session: &MethodSession<S>) -> Result<bool, ShieldError> {
73        Ok(true)
74    }
75
76    async fn forms(&self, provider: P) -> Result<Vec<Form>, ShieldError>;
77
78    async fn call(
79        &self,
80        provider: P,
81        session: &MethodSession<S>,
82        request: Request,
83    ) -> Result<Response, ShieldError>;
84}
85
86#[async_trait]
87pub trait ErasedMethodAction: Send + Sync {
88    fn erased_id(&self) -> String;
89
90    fn erased_name(&self) -> String;
91
92    fn erased_openapi_summary(&self) -> &'static str;
93
94    fn erased_openapi_description(&self) -> &'static str;
95
96    fn erased_method(&self) -> RequestMethod;
97
98    fn erased_condition(
99        &self,
100        provider: &(dyn Any + Send + Sync),
101        base_session: &BaseSession,
102        method_session: &(dyn Any + Send + Sync),
103    ) -> Result<bool, ShieldError>;
104
105    async fn erased_forms(
106        &self,
107        provider: Box<dyn Any + Send + Sync>,
108    ) -> Result<Vec<Form>, ShieldError>;
109
110    async fn erased_call(
111        &self,
112        provider: Box<dyn Any + Send + Sync>,
113        base_session: &BaseSession,
114        method_session: &(dyn Any + Send + Sync),
115        request: Request,
116    ) -> Result<Response, ShieldError>;
117}
118
119#[macro_export]
120macro_rules! erased_method_action {
121    ($action:ident $(, < $( $generic_name:ident : $generic_type:ident ),+ > )*) => {
122        #[async_trait]
123        impl $( < $( $generic_name: $generic_type + 'static ),+ > )* $crate::ErasedMethodAction for $action $( < $( $generic_name ),+ > )* {
124            fn erased_id(&self) -> String {
125                self.id()
126            }
127
128            fn erased_name(&self) -> String {
129                self.name()
130            }
131
132            fn erased_openapi_summary(&self) -> &'static str {
133                self.openapi_summary()
134            }
135
136            fn erased_openapi_description(&self) -> &'static str {
137                self.openapi_description()
138            }
139
140            fn erased_method(&self) -> $crate::RequestMethod {
141                self.method()
142            }
143
144            fn erased_condition(
145                &self,
146                provider: &(dyn std::any::Any + Send + Sync),
147                base_session: &$crate::BaseSession,
148                method_session: &(dyn std::any::Any + Send + Sync)
149            ) -> Result<bool, $crate::ShieldError> {
150                self.condition(
151                    provider.downcast_ref().expect("Provider should be downcast"),
152                    &MethodSession {
153                        base: base_session,
154                        method: method_session.downcast_ref().expect("Session should be downcast"),
155                    },
156                )
157            }
158
159            async fn erased_forms(
160                &self,
161                provider: Box<dyn std::any::Any + Send + Sync>
162            ) -> Result<Vec<$crate::Form>, $crate::ShieldError> {
163                self.forms(*provider.downcast().expect("Provider should be downcast")).await
164            }
165
166            async fn erased_call(
167                &self,
168                provider: Box<dyn std::any::Any + Send + Sync>,
169                base_session: &$crate::BaseSession,
170                method_session: &(dyn std::any::Any + Send + Sync),
171                request: $crate::Request,
172            ) -> Result<$crate::Response, $crate::ShieldError> {
173                self
174                    .call(
175                        *provider.downcast().expect("Provider should be downcast"),
176                        &$crate::MethodSession {
177                            base: base_session,
178                            method: method_session.downcast_ref().expect("Session should be downcast"),
179                        },
180                        request
181                    )
182                    .await
183            }
184        }
185    };
186}