mirror of
https://github.com/docmost/docmost.git
synced 2025-11-13 01:02:43 +10:00
feat(EE): implement SSO group sync for SAML and OIDC (#1452)
* feat: implement SSO group synchronization for SAML and OIDC - Add group_sync column to auth_providers table - Extract groups from SAML attributes (memberOf, groups, roles) - Extract groups from OIDC claims (groups, roles) - Implement case-insensitive group matching with auto-creation - Sync user groups on each SSO login - Ensure only one provider can have group sync enabled at a time - Add group sync toggle to SAML and OIDC configuration forms * rename column
This commit is contained in:
@ -16,6 +16,7 @@ const ssoSchema = z.object({
|
||||
oidcClientSecret: z.string().min(1, "Client secret is required"),
|
||||
isEnabled: z.boolean(),
|
||||
allowSignup: z.boolean(),
|
||||
groupSync: z.boolean(),
|
||||
});
|
||||
|
||||
type SSOFormValues = z.infer<typeof ssoSchema>;
|
||||
@ -36,6 +37,7 @@ export function SsoOIDCForm({ provider, onClose }: SsoFormProps) {
|
||||
oidcClientSecret: provider.oidcClientSecret || "",
|
||||
isEnabled: provider.isEnabled,
|
||||
allowSignup: provider.allowSignup,
|
||||
groupSync: provider.groupSync || false,
|
||||
},
|
||||
validate: zodResolver(ssoSchema),
|
||||
});
|
||||
@ -67,6 +69,9 @@ export function SsoOIDCForm({ provider, onClose }: SsoFormProps) {
|
||||
if (form.isDirty("allowSignup")) {
|
||||
ssoData.allowSignup = values.allowSignup;
|
||||
}
|
||||
if (form.isDirty("groupSync")) {
|
||||
ssoData.groupSync = values.groupSync;
|
||||
}
|
||||
|
||||
await updateSsoProviderMutation.mutateAsync(ssoData);
|
||||
form.resetDirty();
|
||||
@ -119,6 +124,15 @@ export function SsoOIDCForm({ provider, onClose }: SsoFormProps) {
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group justify="space-between">
|
||||
<div>{t("Group sync")}</div>
|
||||
<Switch
|
||||
className={classes.switch}
|
||||
checked={form.values.groupSync}
|
||||
{...form.getInputProps("groupSync")}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group justify="space-between">
|
||||
<div>{t("Enabled")}</div>
|
||||
<Switch
|
||||
|
||||
@ -26,6 +26,7 @@ const ssoSchema = z.object({
|
||||
samlCertificate: z.string().min(1, "SAML Idp Certificate is required"),
|
||||
isEnabled: z.boolean(),
|
||||
allowSignup: z.boolean(),
|
||||
groupSync: z.boolean(),
|
||||
});
|
||||
|
||||
type SSOFormValues = z.infer<typeof ssoSchema>;
|
||||
@ -45,6 +46,7 @@ export function SsoSamlForm({ provider, onClose }: SsoFormProps) {
|
||||
samlCertificate: provider.samlCertificate || "",
|
||||
isEnabled: provider.isEnabled,
|
||||
allowSignup: provider.allowSignup,
|
||||
groupSync: provider.groupSync || false,
|
||||
},
|
||||
validate: zodResolver(ssoSchema),
|
||||
});
|
||||
@ -75,6 +77,9 @@ export function SsoSamlForm({ provider, onClose }: SsoFormProps) {
|
||||
if (form.isDirty("allowSignup")) {
|
||||
ssoData.allowSignup = values.allowSignup;
|
||||
}
|
||||
if (form.isDirty("groupSync")) {
|
||||
ssoData.groupSync = values.groupSync;
|
||||
}
|
||||
|
||||
await updateSsoProviderMutation.mutateAsync(ssoData);
|
||||
form.resetDirty();
|
||||
@ -132,6 +137,15 @@ export function SsoSamlForm({ provider, onClose }: SsoFormProps) {
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group justify="space-between">
|
||||
<div>{t("Group sync")}</div>
|
||||
<Switch
|
||||
className={classes.switch}
|
||||
checked={form.values.groupSync}
|
||||
{...form.getInputProps("groupSync")}
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Group justify="space-between">
|
||||
<div>{t("Enabled")}</div>
|
||||
<Switch
|
||||
|
||||
@ -11,6 +11,7 @@ export interface IAuthProvider {
|
||||
oidcClientSecret: string;
|
||||
allowSignup: boolean;
|
||||
isEnabled: boolean;
|
||||
groupSync: boolean;
|
||||
creatorId: string;
|
||||
workspaceId: string;
|
||||
createdAt: Date;
|
||||
|
||||
Reference in New Issue
Block a user