mz_frontegg_mock/models/
sso.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use super::group::{DefaultRoles, GroupMapping, GroupMappingResponse};
11use chrono::{DateTime, Utc};
12use serde::{Deserialize, Serialize};
13use uuid::Uuid;
14
15#[derive(Deserialize)]
16pub struct SSOConfigCreateRequest {
17    #[serde(default)]
18    pub enabled: bool,
19    #[serde(rename = "ssoEndpoint")]
20    pub sso_endpoint: Option<String>,
21    #[serde(rename = "publicCertificate")]
22    pub public_certificate: Option<String>,
23    #[serde(default)]
24    #[serde(rename = "signRequest")]
25    pub sign_request: bool,
26    #[serde(rename = "acsUrl")]
27    pub acs_url: Option<String>,
28    #[serde(rename = "spEntityId")]
29    pub sp_entity_id: Option<String>,
30    #[serde(rename = "type")]
31    pub config_type: Option<String>,
32    #[serde(rename = "oidcClientId")]
33    pub oidc_client_id: Option<String>,
34    #[serde(rename = "oidcSecret")]
35    pub oidc_secret: Option<String>,
36}
37
38#[derive(Serialize, Deserialize, Clone, Debug)]
39pub struct SSOConfigStorage {
40    pub id: String,
41    pub enabled: bool,
42    pub sso_endpoint: String,
43    pub public_certificate: String,
44    pub sign_request: bool,
45    pub acs_url: String,
46    pub sp_entity_id: String,
47    pub config_type: String,
48    pub oidc_client_id: String,
49    pub oidc_secret: String,
50    pub domains: Vec<Domain>,
51    pub groups: Vec<GroupMapping>,
52    pub default_roles: DefaultRoles,
53    pub generated_verification: Option<String>,
54    pub created_at: Option<DateTime<Utc>>,
55    pub updated_at: Option<DateTime<Utc>>,
56    pub config_metadata: Option<serde_json::Value>,
57    pub override_active_tenant: Option<bool>,
58    pub skip_email_domain_validation: Option<bool>,
59    pub sub_account_access_limit: Option<i32>,
60    pub role_ids: Vec<String>,
61}
62
63#[derive(Serialize)]
64pub struct SSOConfigResponse {
65    pub id: String,
66    pub enabled: bool,
67    #[serde(rename = "ssoEndpoint")]
68    pub sso_endpoint: String,
69    #[serde(rename = "publicCertificate")]
70    pub public_certificate: String,
71    #[serde(rename = "signRequest")]
72    pub sign_request: bool,
73    #[serde(rename = "acsUrl")]
74    pub acs_url: String,
75    #[serde(rename = "spEntityId")]
76    pub sp_entity_id: String,
77    #[serde(rename = "type")]
78    pub config_type: String,
79    #[serde(rename = "oidcClientId")]
80    pub oidc_client_id: String,
81    #[serde(rename = "oidcSecret")]
82    pub oidc_secret: String,
83    pub domains: Vec<DomainResponse>,
84    pub groups: Vec<GroupMappingResponse>,
85    #[serde(rename = "defaultRoles")]
86    pub default_roles: DefaultRoles,
87    #[serde(rename = "generatedVerification")]
88    pub generated_verification: Option<String>,
89    #[serde(rename = "createdAt")]
90    pub created_at: DateTime<Utc>,
91    #[serde(rename = "updatedAt")]
92    pub updated_at: DateTime<Utc>,
93    #[serde(rename = "configMetadata")]
94    pub config_metadata: Option<serde_json::Value>,
95    #[serde(rename = "overrideActiveTenant")]
96    pub override_active_tenant: bool,
97    #[serde(rename = "skipEmailDomainValidation")]
98    pub skip_email_domain_validation: bool,
99    #[serde(rename = "subAccountAccessLimit")]
100    pub sub_account_access_limit: i32,
101    #[serde(rename = "roleIds")]
102    pub role_ids: Vec<String>,
103}
104
105#[derive(Deserialize)]
106pub struct SSOConfigUpdateRequest {
107    pub enabled: Option<bool>,
108    #[serde(rename = "ssoEndpoint")]
109    pub sso_endpoint: Option<String>,
110    #[serde(rename = "publicCertificate")]
111    pub public_certificate: Option<String>,
112    #[serde(rename = "signRequest")]
113    pub sign_request: Option<bool>,
114    #[serde(rename = "acsUrl")]
115    pub acs_url: Option<String>,
116    #[serde(rename = "spEntityId")]
117    pub sp_entity_id: Option<String>,
118    #[serde(rename = "type")]
119    pub config_type: Option<String>,
120    #[serde(rename = "oidcClientId")]
121    pub oidc_client_id: Option<String>,
122    #[serde(rename = "oidcSecret")]
123    pub oidc_secret: Option<String>,
124}
125
126#[derive(Serialize, Deserialize, Clone, Debug)]
127pub struct Domain {
128    #[serde(default)]
129    pub id: String,
130    pub domain: String,
131    #[serde(default)]
132    pub validated: bool,
133    #[serde(default, rename = "ssoConfigId")]
134    pub sso_config_id: String,
135    #[serde(skip_deserializing)]
136    pub txt_record: String,
137}
138
139#[derive(Serialize)]
140pub struct DomainResponse {
141    pub id: String,
142    pub domain: String,
143    pub validated: bool,
144    #[serde(rename = "ssoConfigId")]
145    pub sso_config_id: String,
146    #[serde(rename = "txtRecord")]
147    pub txt_record: String,
148}
149
150#[derive(Deserialize)]
151pub struct DomainUpdateRequest {
152    pub domain: Option<String>,
153    pub validated: Option<bool>,
154}
155
156impl From<SSOConfigStorage> for SSOConfigResponse {
157    fn from(storage: SSOConfigStorage) -> Self {
158        SSOConfigResponse {
159            id: storage.id,
160            enabled: storage.enabled,
161            sso_endpoint: storage.sso_endpoint,
162            public_certificate: storage.public_certificate,
163            sign_request: storage.sign_request,
164            acs_url: storage.acs_url,
165            sp_entity_id: storage.sp_entity_id,
166            config_type: storage.config_type,
167            oidc_client_id: storage.oidc_client_id,
168            oidc_secret: storage.oidc_secret,
169            domains: storage
170                .domains
171                .into_iter()
172                .map(DomainResponse::from)
173                .collect(),
174            groups: storage
175                .groups
176                .into_iter()
177                .map(GroupMappingResponse::from)
178                .collect(),
179            default_roles: storage.default_roles,
180            generated_verification: storage.generated_verification,
181            created_at: storage.created_at.unwrap_or_else(Utc::now),
182            updated_at: storage.updated_at.unwrap_or_else(Utc::now),
183            config_metadata: storage.config_metadata,
184            override_active_tenant: storage.override_active_tenant.unwrap_or(false),
185            skip_email_domain_validation: storage.skip_email_domain_validation.unwrap_or(false),
186            sub_account_access_limit: storage.sub_account_access_limit.unwrap_or(0),
187            role_ids: storage.role_ids,
188        }
189    }
190}
191
192impl From<Domain> for DomainResponse {
193    fn from(domain: Domain) -> Self {
194        let txt_record = format!(
195            "_saml-domain-challenge.{}.{}.{}",
196            Uuid::new_v4(),
197            Uuid::new_v4(),
198            domain.domain
199        );
200
201        DomainResponse {
202            id: domain.id,
203            domain: domain.domain,
204            validated: domain.validated,
205            sso_config_id: domain.sso_config_id,
206            txt_record,
207        }
208    }
209}
210
211impl From<GroupMapping> for GroupMappingResponse {
212    fn from(group: GroupMapping) -> Self {
213        GroupMappingResponse {
214            id: group.id,
215            group: group.group,
216            role_ids: group.role_ids,
217            sso_config_id: group.sso_config_id,
218            enabled: group.enabled,
219        }
220    }
221}