Skip to main content

spiral/api/authn/
objects.rs

1// Generated by tools/service-contracts/rust.py. Do not edit.
2#![doc = "Generated transport-independent contract objects."]
3
4use std::collections::BTreeMap;
5use std::error::Error as StdError;
6use std::fmt::{self, Display, Formatter};
7
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9use serde_json::Value;
10use spiral_contract::error::{ErrorEnvelope, ServiceError};
11use spiral_contract::strict::{DeserializeStrict, Strict};
12use uuid::Uuid;
13
14/// An Organization's decision for one third-party client.
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub enum AppAccessDecision {
17    /// A known contract value.
18    Allow,
19    /// A known contract value.
20    Block,
21    /// A value introduced by a newer server.
22    Unknown(String),
23}
24impl Serialize for AppAccessDecision {
25    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
26        serializer.serialize_str(match self {
27            Self::Allow => "allow",
28            Self::Block => "block",
29            Self::Unknown(value) => value,
30        })
31    }
32}
33impl<'de> Deserialize<'de> for AppAccessDecision {
34    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
35        Ok(match String::deserialize(deserializer)?.as_str() {
36            "allow" => Self::Allow,
37            "block" => Self::Block,
38            value => Self::Unknown(value.to_owned()),
39        })
40    }
41}
42impl<'de> DeserializeStrict<'de> for AppAccessDecision {
43    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
44        #[derive(Deserialize)]
45        enum __Known {
46            #[serde(rename = "allow")]
47            Allow,
48            #[serde(rename = "block")]
49            Block,
50        }
51        Ok(match __Known::deserialize(deserializer)? {
52            __Known::Allow => Self::Allow,
53            __Known::Block => Self::Block,
54        })
55    }
56}
57
58/// One client and the Organization's decision for it.
59#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
60pub struct ClientAppAccess {
61    /// Contract field clientId.
62    #[serde(rename = "clientId")]
63    pub client_id: String,
64    /// Contract field decision.
65    #[serde(rename = "decision")]
66    pub decision: AppAccessDecision,
67}
68impl<'de> DeserializeStrict<'de> for ClientAppAccess {
69    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
70        #[derive(Deserialize)]
71        #[serde(deny_unknown_fields)]
72        struct __Wire {
73            #[serde(rename = "clientId")]
74            client_id: Strict<String>,
75            #[serde(rename = "decision")]
76            decision: Strict<AppAccessDecision>,
77        }
78        let wire = __Wire::deserialize(deserializer)?;
79        Ok(Self {
80            client_id: wire.client_id.0,
81            decision: wire.decision.0,
82        })
83    }
84}
85
86/// One exact HTTPS callback. Its browser CORS origin is derived from the URI.
87#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
88pub struct ClientRedirect {
89    /// Contract field redirectUri.
90    #[serde(rename = "redirectUri")]
91    pub redirect_uri: String,
92}
93impl<'de> DeserializeStrict<'de> for ClientRedirect {
94    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
95        #[derive(Deserialize)]
96        #[serde(deny_unknown_fields)]
97        struct __Wire {
98            #[serde(rename = "redirectUri")]
99            redirect_uri: Strict<String>,
100        }
101        let wire = __Wire::deserialize(deserializer)?;
102        Ok(Self {
103            redirect_uri: wire.redirect_uri.0,
104        })
105    }
106}
107
108/// A client that signs users in with user consent, or obtains tokens for itself. Sign-in requires
109/// exact callbacks, PKCE and user consent. Background tokens name the client as subject and carry
110/// no authority of their own: authorization decides what the subject may do. A client can exist
111/// before it has a credential. A token_exchange-only Connection registration names the external
112/// audiences for identities that its owning registrar requests.
113#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
114pub struct ClientRegistration {
115    /// Contract field audience.
116    #[serde(rename = "audience")]
117    pub audience: Vec<String>,
118    /// Contract field clientName.
119    #[serde(rename = "clientName")]
120    pub client_name: String,
121    /// Contract field enabled.
122    #[serde(rename = "enabled")]
123    #[serde(default, skip_serializing_if = "Option::is_none")]
124    pub enabled: Option<bool>,
125    /// Contract field grantTypes.
126    #[serde(rename = "grantTypes")]
127    pub grant_types: Vec<GrantType>,
128    /// Contract field jwks.
129    #[serde(rename = "jwks")]
130    #[serde(default, skip_serializing_if = "Option::is_none")]
131    pub jwks: Option<Value>,
132    /// Contract field jwtBearerIssuers.
133    #[serde(rename = "jwtBearerIssuers")]
134    pub jwt_bearer_issuers: Vec<JwtBearerIssuer>,
135    /// Contract field signIn.
136    #[serde(rename = "signIn")]
137    #[serde(default, skip_serializing_if = "Option::is_none")]
138    pub sign_in: Option<SignInRegistration>,
139}
140impl<'de> DeserializeStrict<'de> for ClientRegistration {
141    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
142        #[derive(Deserialize)]
143        #[serde(deny_unknown_fields)]
144        struct __Wire {
145            #[serde(rename = "audience")]
146            audience: Strict<Vec<String>>,
147            #[serde(rename = "clientName")]
148            client_name: Strict<String>,
149            #[serde(rename = "enabled")]
150            #[serde(default)]
151            enabled: Strict<Option<bool>>,
152            #[serde(rename = "grantTypes")]
153            grant_types: Strict<Vec<GrantType>>,
154            #[serde(rename = "jwks")]
155            #[serde(default)]
156            jwks: Strict<Option<Value>>,
157            #[serde(rename = "jwtBearerIssuers")]
158            jwt_bearer_issuers: Strict<Vec<JwtBearerIssuer>>,
159            #[serde(rename = "signIn")]
160            #[serde(default)]
161            sign_in: Strict<Option<SignInRegistration>>,
162        }
163        let wire = __Wire::deserialize(deserializer)?;
164        Ok(Self {
165            audience: wire.audience.0,
166            client_name: wire.client_name.0,
167            enabled: wire.enabled.0,
168            grant_types: wire.grant_types.0,
169            jwks: wire.jwks.0,
170            jwt_bearer_issuers: wire.jwt_bearer_issuers.0,
171            sign_in: wire.sign_in.0,
172        })
173    }
174}
175
176/// The verified OAuth client and callback shown by the consent application.
177#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
178pub struct ConsentClient {
179    /// Contract field id.
180    #[serde(rename = "id")]
181    pub id: String,
182    /// Contract field loopbackOnly.
183    #[serde(rename = "loopbackOnly")]
184    pub loopback_only: bool,
185    /// Contract field managed.
186    #[serde(rename = "managed")]
187    pub managed: bool,
188    /// Contract field name.
189    #[serde(rename = "name")]
190    pub name: String,
191    /// Contract field publisher.
192    #[serde(rename = "publisher")]
193    pub publisher: String,
194    /// Contract field publisherName.
195    #[serde(rename = "publisherName")]
196    #[serde(default, skip_serializing_if = "Option::is_none")]
197    pub publisher_name: Option<String>,
198    /// Contract field redirectHost.
199    #[serde(rename = "redirectHost")]
200    pub redirect_host: String,
201}
202impl<'de> DeserializeStrict<'de> for ConsentClient {
203    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
204        #[derive(Deserialize)]
205        #[serde(deny_unknown_fields)]
206        struct __Wire {
207            #[serde(rename = "id")]
208            id: Strict<String>,
209            #[serde(rename = "loopbackOnly")]
210            loopback_only: Strict<bool>,
211            #[serde(rename = "managed")]
212            managed: Strict<bool>,
213            #[serde(rename = "name")]
214            name: Strict<String>,
215            #[serde(rename = "publisher")]
216            publisher: Strict<String>,
217            #[serde(rename = "publisherName")]
218            #[serde(default)]
219            publisher_name: Strict<Option<String>>,
220            #[serde(rename = "redirectHost")]
221            redirect_host: Strict<String>,
222        }
223        let wire = __Wire::deserialize(deserializer)?;
224        Ok(Self {
225            id: wire.id.0,
226            loopback_only: wire.loopback_only.0,
227            managed: wire.managed.0,
228            name: wire.name.0,
229            publisher: wire.publisher.0,
230            publisher_name: wire.publisher_name.0,
231            redirect_host: wire.redirect_host.0,
232        })
233    }
234}
235
236/// Accept only the listed requested scopes, or reject the authorization.
237#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
238pub struct ConsentDecision {
239    /// Contract field approve.
240    #[serde(rename = "approve")]
241    pub approve: bool,
242    /// Contract field scopes.
243    #[serde(rename = "scopes")]
244    pub scopes: Vec<String>,
245}
246impl<'de> DeserializeStrict<'de> for ConsentDecision {
247    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
248        #[derive(Deserialize)]
249        #[serde(deny_unknown_fields)]
250        struct __Wire {
251            #[serde(rename = "approve")]
252            approve: Strict<bool>,
253            #[serde(rename = "scopes")]
254            scopes: Strict<Vec<String>>,
255        }
256        let wire = __Wire::deserialize(deserializer)?;
257        Ok(Self {
258            approve: wire.approve.0,
259            scopes: wire.scopes.0,
260        })
261    }
262}
263
264/// Return the initiating browser to this authorization-server URL to finish consent.
265#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
266pub struct ConsentRedirect {
267    /// Contract field redirectTo.
268    #[serde(rename = "redirectTo")]
269    pub redirect_to: String,
270}
271impl<'de> DeserializeStrict<'de> for ConsentRedirect {
272    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
273        #[derive(Deserialize)]
274        #[serde(deny_unknown_fields)]
275        struct __Wire {
276            #[serde(rename = "redirectTo")]
277            redirect_to: Strict<String>,
278        }
279        let wire = __Wire::deserialize(deserializer)?;
280        Ok(Self {
281            redirect_to: wire.redirect_to.0,
282        })
283    }
284}
285
286/// The requested delegation. A challenge contains no access or refresh token.
287#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
288pub struct ConsentRequest {
289    /// Contract field client.
290    #[serde(rename = "client")]
291    pub client: ConsentClient,
292    /// Contract field resource.
293    #[serde(rename = "resource")]
294    pub resource: String,
295    /// Contract field scopes.
296    #[serde(rename = "scopes")]
297    pub scopes: Vec<String>,
298    /// Contract field skip.
299    #[serde(rename = "skip")]
300    pub skip: bool,
301    /// Contract field subject.
302    #[serde(rename = "subject")]
303    pub subject: ConsentSubject,
304}
305impl<'de> DeserializeStrict<'de> for ConsentRequest {
306    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
307        #[derive(Deserialize)]
308        #[serde(deny_unknown_fields)]
309        struct __Wire {
310            #[serde(rename = "client")]
311            client: Strict<ConsentClient>,
312            #[serde(rename = "resource")]
313            resource: Strict<String>,
314            #[serde(rename = "scopes")]
315            scopes: Strict<Vec<String>>,
316            #[serde(rename = "skip")]
317            skip: Strict<bool>,
318            #[serde(rename = "subject")]
319            subject: Strict<ConsentSubject>,
320        }
321        let wire = __Wire::deserialize(deserializer)?;
322        Ok(Self {
323            client: wire.client.0,
324            resource: wire.resource.0,
325            scopes: wire.scopes.0,
326            skip: wire.skip.0,
327            subject: wire.subject.0,
328        })
329    }
330}
331
332/// The authenticated user and Organization bound to this authorization.
333#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
334pub struct ConsentSubject {
335    /// Contract field organizationId.
336    #[serde(rename = "organizationId")]
337    pub organization_id: String,
338    /// Contract field organizationName.
339    #[serde(rename = "organizationName")]
340    pub organization_name: String,
341    /// Contract field userId.
342    #[serde(rename = "userId")]
343    pub user_id: String,
344}
345impl<'de> DeserializeStrict<'de> for ConsentSubject {
346    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
347        #[derive(Deserialize)]
348        #[serde(deny_unknown_fields)]
349        struct __Wire {
350            #[serde(rename = "organizationId")]
351            organization_id: Strict<String>,
352            #[serde(rename = "organizationName")]
353            organization_name: Strict<String>,
354            #[serde(rename = "userId")]
355            user_id: Strict<String>,
356        }
357        let wire = __Wire::deserialize(deserializer)?;
358        Ok(Self {
359            organization_id: wire.organization_id.0,
360            organization_name: wire.organization_name.0,
361            user_id: wire.user_id.0,
362        })
363    }
364}
365
366/// A grant that a client uses at the token endpoint. client_credentials authenticates the client
367/// with a private_key_jwt assertion signed by a key in its jwks. jwt_bearer is the RFC 7523 grant
368/// for an ID token from one of its jwtBearerIssuers.
369#[derive(Clone, Debug, PartialEq, Eq)]
370pub enum GrantType {
371    /// A known contract value.
372    ClientCredentials,
373    /// A known contract value.
374    JwtBearer,
375    /// A known contract value.
376    TokenExchange,
377    /// A known contract value.
378    AuthorizationCode,
379    /// A known contract value.
380    RefreshToken,
381    /// A value introduced by a newer server.
382    Unknown(String),
383}
384impl Serialize for GrantType {
385    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
386        serializer.serialize_str(match self {
387            Self::ClientCredentials => "client_credentials",
388            Self::JwtBearer => "jwt_bearer",
389            Self::TokenExchange => "token_exchange",
390            Self::AuthorizationCode => "authorization_code",
391            Self::RefreshToken => "refresh_token",
392            Self::Unknown(value) => value,
393        })
394    }
395}
396impl<'de> Deserialize<'de> for GrantType {
397    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
398        Ok(match String::deserialize(deserializer)?.as_str() {
399            "client_credentials" => Self::ClientCredentials,
400            "jwt_bearer" => Self::JwtBearer,
401            "token_exchange" => Self::TokenExchange,
402            "authorization_code" => Self::AuthorizationCode,
403            "refresh_token" => Self::RefreshToken,
404            value => Self::Unknown(value.to_owned()),
405        })
406    }
407}
408impl<'de> DeserializeStrict<'de> for GrantType {
409    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
410        #[derive(Deserialize)]
411        enum __Known {
412            #[serde(rename = "client_credentials")]
413            ClientCredentials,
414            #[serde(rename = "jwt_bearer")]
415            JwtBearer,
416            #[serde(rename = "token_exchange")]
417            TokenExchange,
418            #[serde(rename = "authorization_code")]
419            AuthorizationCode,
420            #[serde(rename = "refresh_token")]
421            RefreshToken,
422        }
423        Ok(match __Known::deserialize(deserializer)? {
424            __Known::ClientCredentials => Self::ClientCredentials,
425            __Known::JwtBearer => Self::JwtBearer,
426            __Known::TokenExchange => Self::TokenExchange,
427            __Known::AuthorizationCode => Self::AuthorizationCode,
428            __Known::RefreshToken => Self::RefreshToken,
429        })
430    }
431}
432
433/// An identity provider whose ID tokens identify the client. A token must carry every listed claim
434/// value, and its audience must be the token endpoint unless audience names another. Naming one
435/// departs from RFC 7523 section 3, for an issuer whose tokens cannot name the authorization
436/// server.
437#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
438pub struct JwtBearerIssuer {
439    /// Contract field audience.
440    #[serde(rename = "audience")]
441    #[serde(default, skip_serializing_if = "Option::is_none")]
442    pub audience: Option<String>,
443    /// Contract field claims.
444    #[serde(rename = "claims")]
445    pub claims: BTreeMap<String, String>,
446    /// Contract field issuer.
447    #[serde(rename = "issuer")]
448    pub issuer: String,
449}
450impl<'de> DeserializeStrict<'de> for JwtBearerIssuer {
451    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
452        #[derive(Deserialize)]
453        #[serde(deny_unknown_fields)]
454        struct __Wire {
455            #[serde(rename = "audience")]
456            #[serde(default)]
457            audience: Strict<Option<String>>,
458            #[serde(rename = "claims")]
459            claims: Strict<BTreeMap<String, String>>,
460            #[serde(rename = "issuer")]
461            issuer: Strict<String>,
462        }
463        let wire = __Wire::deserialize(deserializer)?;
464        Ok(Self {
465            audience: wire.audience.0,
466            claims: wire.claims.0,
467            issuer: wire.issuer.0,
468        })
469    }
470}
471
472/// Which third-party clients an Organization's users may sign in to. A client's own decision takes
473/// precedence over unlisted.
474#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
475pub struct OrganizationAppAccess {
476    /// Contract field clients.
477    #[serde(rename = "clients")]
478    pub clients: Vec<ClientAppAccess>,
479    /// Contract field unlisted.
480    #[serde(rename = "unlisted")]
481    pub unlisted: UnlistedAppAccess,
482}
483impl<'de> DeserializeStrict<'de> for OrganizationAppAccess {
484    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
485        #[derive(Deserialize)]
486        #[serde(deny_unknown_fields)]
487        struct __Wire {
488            #[serde(rename = "clients")]
489            clients: Strict<Vec<ClientAppAccess>>,
490            #[serde(rename = "unlisted")]
491            unlisted: Strict<UnlistedAppAccess>,
492        }
493        let wire = __Wire::deserialize(deserializer)?;
494        Ok(Self {
495            clients: wire.clients.0,
496            unlisted: wire.unlisted.0,
497        })
498    }
499}
500
501/// Whose users a sign-in client is built for. Absent means internal.
502#[derive(Clone, Debug, PartialEq, Eq)]
503pub enum SignInAudience {
504    /// A known contract value.
505    Internal,
506    /// A known contract value.
507    Public,
508    /// A value introduced by a newer server.
509    Unknown(String),
510}
511impl Serialize for SignInAudience {
512    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
513        serializer.serialize_str(match self {
514            Self::Internal => "internal",
515            Self::Public => "public",
516            Self::Unknown(value) => value,
517        })
518    }
519}
520impl<'de> Deserialize<'de> for SignInAudience {
521    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
522        Ok(match String::deserialize(deserializer)?.as_str() {
523            "internal" => Self::Internal,
524            "public" => Self::Public,
525            value => Self::Unknown(value.to_owned()),
526        })
527    }
528}
529impl<'de> DeserializeStrict<'de> for SignInAudience {
530    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
531        #[derive(Deserialize)]
532        enum __Known {
533            #[serde(rename = "internal")]
534            Internal,
535            #[serde(rename = "public")]
536            Public,
537        }
538        Ok(match __Known::deserialize(deserializer)? {
539            __Known::Internal => Self::Internal,
540            __Known::Public => Self::Public,
541        })
542    }
543}
544
545/// A third-party sign-in client, with exact callbacks and a publisher shown at consent.
546/// organizationId is required for registrar-managed sign-in and names the developer Organization.
547/// An internal audience admits only that Organization's users; a public audience admits other
548/// Organizations once Spiral has reviewed the client, subject to each Organization's app access.
549/// Existing registrations without an organizationId cannot sign users in. allowedCorsOrigins lists
550/// the exact browser origins whose scripts may call the token endpoint as the client, and to which
551/// resource servers answer its exchanged tokens.
552#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
553pub struct SignInRegistration {
554    /// Contract field allowedCorsOrigins.
555    #[serde(rename = "allowedCorsOrigins")]
556    #[serde(default, skip_serializing_if = "Option::is_none")]
557    pub allowed_cors_origins: Option<Vec<String>>,
558    /// Contract field audience.
559    #[serde(rename = "audience")]
560    #[serde(default, skip_serializing_if = "Option::is_none")]
561    pub audience: Option<SignInAudience>,
562    /// Contract field organizationId.
563    #[serde(rename = "organizationId")]
564    #[serde(default, skip_serializing_if = "Option::is_none")]
565    pub organization_id: Option<String>,
566    /// Contract field publisher.
567    #[serde(rename = "publisher")]
568    pub publisher: String,
569    /// Contract field redirectUris.
570    #[serde(rename = "redirectUris")]
571    pub redirect_uris: Vec<String>,
572    /// Contract field resources.
573    #[serde(rename = "resources")]
574    pub resources: Vec<String>,
575    /// Contract field scopes.
576    #[serde(rename = "scopes")]
577    pub scopes: Vec<String>,
578}
579impl<'de> DeserializeStrict<'de> for SignInRegistration {
580    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
581        #[derive(Deserialize)]
582        #[serde(deny_unknown_fields)]
583        struct __Wire {
584            #[serde(rename = "allowedCorsOrigins")]
585            #[serde(default)]
586            allowed_cors_origins: Strict<Option<Vec<String>>>,
587            #[serde(rename = "audience")]
588            #[serde(default)]
589            audience: Strict<Option<SignInAudience>>,
590            #[serde(rename = "organizationId")]
591            #[serde(default)]
592            organization_id: Strict<Option<String>>,
593            #[serde(rename = "publisher")]
594            publisher: Strict<String>,
595            #[serde(rename = "redirectUris")]
596            redirect_uris: Strict<Vec<String>>,
597            #[serde(rename = "resources")]
598            resources: Strict<Vec<String>>,
599            #[serde(rename = "scopes")]
600            scopes: Strict<Vec<String>>,
601        }
602        let wire = __Wire::deserialize(deserializer)?;
603        Ok(Self {
604            allowed_cors_origins: wire.allowed_cors_origins.0,
605            audience: wire.audience.0,
606            organization_id: wire.organization_id.0,
607            publisher: wire.publisher.0,
608            redirect_uris: wire.redirect_uris.0,
609            resources: wire.resources.0,
610            scopes: wire.scopes.0,
611        })
612    }
613}
614
615/// What an Organization does with third-party clients it has not decided on: allow those Spiral
616/// reviewed, or block them.
617#[derive(Clone, Debug, PartialEq, Eq)]
618pub enum UnlistedAppAccess {
619    /// A known contract value.
620    AllowReviewed,
621    /// A known contract value.
622    Block,
623    /// A value introduced by a newer server.
624    Unknown(String),
625}
626impl Serialize for UnlistedAppAccess {
627    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
628        serializer.serialize_str(match self {
629            Self::AllowReviewed => "allow_reviewed",
630            Self::Block => "block",
631            Self::Unknown(value) => value,
632        })
633    }
634}
635impl<'de> Deserialize<'de> for UnlistedAppAccess {
636    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
637        Ok(match String::deserialize(deserializer)?.as_str() {
638            "allow_reviewed" => Self::AllowReviewed,
639            "block" => Self::Block,
640            value => Self::Unknown(value.to_owned()),
641        })
642    }
643}
644impl<'de> DeserializeStrict<'de> for UnlistedAppAccess {
645    fn deserialize_strict<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
646        #[derive(Deserialize)]
647        enum __Known {
648            #[serde(rename = "allow_reviewed")]
649            AllowReviewed,
650            #[serde(rename = "block")]
651            Block,
652        }
653        Ok(match __Known::deserialize(deserializer)? {
654            __Known::AllowReviewed => Self::AllowReviewed,
655            __Known::Block => Self::Block,
656        })
657    }
658}
659
660/// Typed errors declared by this service contract.
661#[derive(Clone, Debug, PartialEq, Eq)]
662pub enum AuthnError {
663    /// Authn:ClientConflict.
664    ClientConflict { client_id: String },
665    /// Authn:ClientNotFound.
666    ClientNotFound { client_id: String },
667    /// Authn:ConsentConflict.
668    ConsentConflict { reason: String },
669    /// Authn:InvalidClient.
670    InvalidClient { reason: String },
671    /// Authn:InvalidConsent.
672    InvalidConsent { reason: String },
673}
674impl AuthnError {
675    /// HTTP status for this declared error.
676    pub fn status(&self) -> u16 {
677        match self {
678            Self::ClientConflict { .. } => 409,
679            Self::ClientNotFound { .. } => 404,
680            Self::ConsentConflict { .. } => 409,
681            Self::InvalidClient { .. } => 400,
682            Self::InvalidConsent { .. } => 400,
683        }
684    }
685    /// Serialize only contract-declared error parameters.
686    pub fn envelope(&self, instance: String) -> ErrorEnvelope {
687        match self {
688            Self::ClientConflict { client_id } => {
689                let mut envelope = ErrorEnvelope::new("CONFLICT", "Authn:ClientConflict", instance);
690                envelope
691                    .parameters
692                    .insert("clientId".into(), client_id.to_string());
693                envelope
694            }
695            Self::ClientNotFound { client_id } => {
696                let mut envelope =
697                    ErrorEnvelope::new("NOT_FOUND", "Authn:ClientNotFound", instance);
698                envelope
699                    .parameters
700                    .insert("clientId".into(), client_id.to_string());
701                envelope
702            }
703            Self::ConsentConflict { reason } => {
704                let mut envelope =
705                    ErrorEnvelope::new("CONFLICT", "Authn:ConsentConflict", instance);
706                envelope
707                    .parameters
708                    .insert("reason".into(), reason.to_string());
709                envelope
710            }
711            Self::InvalidClient { reason } => {
712                let mut envelope =
713                    ErrorEnvelope::new("INVALID_ARGUMENT", "Authn:InvalidClient", instance);
714                envelope
715                    .parameters
716                    .insert("reason".into(), reason.to_string());
717                envelope
718            }
719            Self::InvalidConsent { reason } => {
720                let mut envelope =
721                    ErrorEnvelope::new("INVALID_ARGUMENT", "Authn:InvalidConsent", instance);
722                envelope
723                    .parameters
724                    .insert("reason".into(), reason.to_string());
725                envelope
726            }
727        }
728    }
729    /// Decode a declared error and its typed error parameters.
730    pub fn decode_envelope(envelope: &ErrorEnvelope) -> Option<Self> {
731        if envelope.error_instance_id.len() != 36
732            || Uuid::parse_str(&envelope.error_instance_id).is_err()
733        {
734            return None;
735        }
736        match envelope.error_name.as_str() {
737            "Authn:ClientConflict" => {
738                if envelope.error_code != "CONFLICT" {
739                    return None;
740                }
741                let client_id = envelope.parameters.get("clientId")?.clone();
742                Some(Self::ClientConflict { client_id })
743            }
744            "Authn:ClientNotFound" => {
745                if envelope.error_code != "NOT_FOUND" {
746                    return None;
747                }
748                let client_id = envelope.parameters.get("clientId")?.clone();
749                Some(Self::ClientNotFound { client_id })
750            }
751            "Authn:ConsentConflict" => {
752                if envelope.error_code != "CONFLICT" {
753                    return None;
754                }
755                let reason = envelope.parameters.get("reason")?.clone();
756                Some(Self::ConsentConflict { reason })
757            }
758            "Authn:InvalidClient" => {
759                if envelope.error_code != "INVALID_ARGUMENT" {
760                    return None;
761                }
762                let reason = envelope.parameters.get("reason")?.clone();
763                Some(Self::InvalidClient { reason })
764            }
765            "Authn:InvalidConsent" => {
766                if envelope.error_code != "INVALID_ARGUMENT" {
767                    return None;
768                }
769                let reason = envelope.parameters.get("reason")?.clone();
770                Some(Self::InvalidConsent { reason })
771            }
772            _ => None,
773        }
774    }
775}
776impl Display for AuthnError {
777    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
778        match self {
779            Self::ClientConflict { client_id } => {
780                write!(formatter, "Authn:ClientConflict (clientId: {})", client_id)
781            }
782            Self::ClientNotFound { client_id } => {
783                write!(formatter, "Authn:ClientNotFound (clientId: {})", client_id)
784            }
785            Self::ConsentConflict { reason } => {
786                write!(formatter, "Authn:ConsentConflict (reason: {})", reason)
787            }
788            Self::InvalidClient { reason } => {
789                write!(formatter, "Authn:InvalidClient (reason: {})", reason)
790            }
791            Self::InvalidConsent { reason } => {
792                write!(formatter, "Authn:InvalidConsent (reason: {})", reason)
793            }
794        }
795    }
796}
797impl StdError for AuthnError {}
798impl ServiceError for AuthnError {
799    fn to_envelope(&self, instance: String) -> ErrorEnvelope {
800        Self::envelope(self, instance)
801    }
802    fn from_envelope(envelope: &ErrorEnvelope) -> Option<Self> {
803        Self::decode_envelope(envelope)
804    }
805}