Skip to main content

openauth_plugins/organization/
options.rs

1use openauth_core::db::TableOptions;
2use serde_json::{json, Value};
3
4use super::hooks::OrganizationHooks;
5use super::{Invitation, Member, Organization};
6use std::sync::Arc;
7
8pub type SendInvitationEmailHook =
9    Arc<dyn Fn(&InvitationEmail) -> Result<(), openauth_core::error::OpenAuthError> + Send + Sync>;
10
11#[derive(Clone)]
12pub struct OrganizationOptions {
13    pub allow_user_to_create_organization: bool,
14    pub organization_limit: Option<usize>,
15    pub creator_role: String,
16    pub membership_limit: usize,
17    pub invitation_expires_in: i64,
18    pub invitation_limit: usize,
19    pub cancel_pending_invitations_on_re_invite: bool,
20    pub require_email_verification_on_invitation: bool,
21    pub disable_organization_deletion: bool,
22    pub hooks: OrganizationHooks,
23    pub send_invitation_email: Option<SendInvitationEmailHook>,
24    pub teams: TeamOptions,
25    pub dynamic_access_control: DynamicAccessControlOptions,
26    pub custom_roles: std::collections::BTreeMap<String, serde_json::Value>,
27    pub schema: OrganizationSchemaOptions,
28}
29
30#[derive(Clone, Debug, PartialEq, Eq)]
31pub struct TeamOptions {
32    pub enabled: bool,
33    pub create_default_team: bool,
34    pub maximum_teams: Option<usize>,
35    pub maximum_members_per_team: Option<usize>,
36    pub allow_removing_all_teams: bool,
37}
38
39#[derive(Clone, Debug, Default, PartialEq, Eq)]
40pub struct DynamicAccessControlOptions {
41    pub enabled: bool,
42    pub maximum_roles_per_organization: Option<usize>,
43}
44
45#[derive(Clone, Debug, Default, PartialEq, Eq)]
46pub struct OrganizationSchemaOptions {
47    pub organization: TableOptions,
48    pub member: TableOptions,
49    pub invitation: TableOptions,
50    pub team: TableOptions,
51    pub team_member: TableOptions,
52    pub organization_role: TableOptions,
53}
54
55#[derive(Debug, Clone)]
56pub struct InvitationEmail {
57    pub id: String,
58    pub role: String,
59    pub email: String,
60    pub organization: Organization,
61    pub invitation: Invitation,
62    pub inviter: Member,
63}
64
65impl Default for OrganizationOptions {
66    fn default() -> Self {
67        Self {
68            allow_user_to_create_organization: true,
69            organization_limit: None,
70            creator_role: "owner".to_owned(),
71            membership_limit: 100,
72            invitation_expires_in: 60 * 60 * 48,
73            invitation_limit: 100,
74            cancel_pending_invitations_on_re_invite: false,
75            require_email_verification_on_invitation: false,
76            disable_organization_deletion: false,
77            hooks: OrganizationHooks::default(),
78            send_invitation_email: None,
79            teams: TeamOptions::default(),
80            dynamic_access_control: DynamicAccessControlOptions::default(),
81            custom_roles: std::collections::BTreeMap::new(),
82            schema: OrganizationSchemaOptions::default(),
83        }
84    }
85}
86
87impl Default for TeamOptions {
88    fn default() -> Self {
89        Self {
90            enabled: false,
91            create_default_team: true,
92            maximum_teams: None,
93            maximum_members_per_team: None,
94            allow_removing_all_teams: false,
95        }
96    }
97}
98
99impl OrganizationOptions {
100    pub fn builder() -> OrganizationOptionsBuilder {
101        OrganizationOptionsBuilder::default()
102    }
103
104    pub(crate) fn to_metadata(&self) -> Value {
105        json!({
106            "allowUserToCreateOrganization": self.allow_user_to_create_organization,
107            "organizationLimit": self.organization_limit,
108            "creatorRole": self.creator_role,
109            "membershipLimit": self.membership_limit,
110            "invitationExpiresIn": self.invitation_expires_in,
111            "invitationLimit": self.invitation_limit,
112            "cancelPendingInvitationsOnReInvite": self.cancel_pending_invitations_on_re_invite,
113            "requireEmailVerificationOnInvitation": self.require_email_verification_on_invitation,
114            "disableOrganizationDeletion": self.disable_organization_deletion,
115            "teams": {
116                "enabled": self.teams.enabled,
117                "defaultTeam": { "enabled": self.teams.create_default_team },
118                "maximumTeams": self.teams.maximum_teams,
119                "maximumMembersPerTeam": self.teams.maximum_members_per_team,
120                "allowRemovingAllTeams": self.teams.allow_removing_all_teams,
121            },
122            "dynamicAccessControl": {
123                "enabled": self.dynamic_access_control.enabled,
124                "maximumRolesPerOrganization": self.dynamic_access_control.maximum_roles_per_organization,
125            },
126        })
127    }
128}
129
130#[derive(Clone, Default)]
131pub struct OrganizationOptionsBuilder {
132    options: OrganizationOptions,
133}
134
135impl OrganizationOptionsBuilder {
136    pub fn allow_user_to_create_organization(mut self, allow: bool) -> Self {
137        self.options.allow_user_to_create_organization = allow;
138        self
139    }
140
141    pub fn organization_limit(mut self, limit: usize) -> Self {
142        self.options.organization_limit = Some(limit);
143        self
144    }
145
146    pub fn creator_role(mut self, role: impl Into<String>) -> Self {
147        self.options.creator_role = role.into();
148        self
149    }
150
151    pub fn membership_limit(mut self, limit: usize) -> Self {
152        self.options.membership_limit = limit;
153        self
154    }
155
156    pub fn invitation_expires_in(mut self, seconds: i64) -> Self {
157        self.options.invitation_expires_in = seconds;
158        self
159    }
160
161    pub fn invitation_limit(mut self, limit: usize) -> Self {
162        self.options.invitation_limit = limit;
163        self
164    }
165
166    pub fn cancel_pending_invitations_on_re_invite(mut self, cancel: bool) -> Self {
167        self.options.cancel_pending_invitations_on_re_invite = cancel;
168        self
169    }
170
171    pub fn require_email_verification_on_invitation(mut self, require: bool) -> Self {
172        self.options.require_email_verification_on_invitation = require;
173        self
174    }
175
176    pub fn disable_organization_deletion(mut self, disable: bool) -> Self {
177        self.options.disable_organization_deletion = disable;
178        self
179    }
180
181    pub fn hooks(mut self, hooks: OrganizationHooks) -> Self {
182        self.options.hooks = hooks;
183        self
184    }
185
186    pub fn send_invitation_email(mut self, hook: SendInvitationEmailHook) -> Self {
187        self.options.send_invitation_email = Some(hook);
188        self
189    }
190
191    pub fn teams(mut self, teams: TeamOptions) -> Self {
192        self.options.teams = teams;
193        self
194    }
195
196    pub fn dynamic_access_control(mut self, options: DynamicAccessControlOptions) -> Self {
197        self.options.dynamic_access_control = options;
198        self
199    }
200
201    pub fn custom_role(mut self, role: impl Into<String>, permissions: serde_json::Value) -> Self {
202        self.options.custom_roles.insert(role.into(), permissions);
203        self
204    }
205
206    pub fn schema(mut self, schema: OrganizationSchemaOptions) -> Self {
207        self.options.schema = schema;
208        self
209    }
210
211    pub fn build(self) -> OrganizationOptions {
212        self.options
213    }
214}