mirror of
https://github.com/documenso/documenso.git
synced 2026-06-22 04:12:06 +10:00
feat: remove default personal orgs from custom sso (#2741)
This commit is contained in:
@@ -51,6 +51,7 @@ const ZProviderFormSchema = ZUpdateOrganisationAuthenticationPortalRequestSchema
|
||||
clientId: true,
|
||||
autoProvisionUsers: true,
|
||||
defaultOrganisationRole: true,
|
||||
allowPersonalOrganisations: true,
|
||||
})
|
||||
.extend({
|
||||
clientSecret: z.string().nullable(),
|
||||
@@ -120,6 +121,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
|
||||
autoProvisionUsers: authenticationPortal.autoProvisionUsers,
|
||||
defaultOrganisationRole: authenticationPortal.defaultOrganisationRole,
|
||||
allowedDomains: authenticationPortal.allowedDomains.join(' '),
|
||||
allowPersonalOrganisations: authenticationPortal.allowPersonalOrganisations,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -161,6 +163,7 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
|
||||
autoProvisionUsers: values.autoProvisionUsers,
|
||||
defaultOrganisationRole: values.defaultOrganisationRole,
|
||||
allowedDomains: values.allowedDomains.split(' ').filter(Boolean),
|
||||
allowPersonalOrganisations: values.allowPersonalOrganisations,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -390,6 +393,30 @@ const SSOProviderForm = ({ authenticationPortal }: SSOProviderFormProps) => {
|
||||
)}
|
||||
/> */}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="allowPersonalOrganisations"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex items-center justify-between rounded-lg border px-4 py-3">
|
||||
<div className="space-y-0.5">
|
||||
<FormLabel>
|
||||
<Trans>Allow Personal Organisations</Trans>
|
||||
</FormLabel>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<Trans>
|
||||
When enabled, users signing in via SSO for the first time will also receive
|
||||
their own personal organisation.
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
<FormControl>
|
||||
<Switch checked={field.value} onCheckedChange={field.onChange} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="enabled"
|
||||
|
||||
@@ -76,7 +76,10 @@ export const handleOAuthOrganisationCallbackUrl = async (
|
||||
},
|
||||
});
|
||||
|
||||
await onCreateUserHook(userToLink).catch((err) => {
|
||||
await onCreateUserHook(userToLink, {
|
||||
skipPersonalOrganisation:
|
||||
!organisation.organisationAuthenticationPortal.allowPersonalOrganisations,
|
||||
}).catch((err) => {
|
||||
// Todo: (RR7) Add logging.
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
@@ -60,13 +60,27 @@ export const createUser = async ({ name, email, password, signature }: CreateUse
|
||||
return user;
|
||||
};
|
||||
|
||||
export type OnCreateUserHookOptions = {
|
||||
/**
|
||||
* When true, do not create a "Personal Organisation" for the new user.
|
||||
* Used by the Organisation SSO signup path, where the user is intended
|
||||
* to operate inside the SSO organisation rather than a personal space.
|
||||
*
|
||||
* Defaults to false — preserves the historical behaviour of creating a
|
||||
* personal organisation for every new user.
|
||||
*/
|
||||
skipPersonalOrganisation?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Should be run after a user is created, example during email password signup or google sign in.
|
||||
*
|
||||
* @returns User
|
||||
*/
|
||||
export const onCreateUserHook = async (user: User) => {
|
||||
await createPersonalOrganisation({ userId: user.id });
|
||||
export const onCreateUserHook = async (user: User, options: OnCreateUserHookOptions = {}) => {
|
||||
if (!options.skipPersonalOrganisation) {
|
||||
await createPersonalOrganisation({ userId: user.id });
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
-- AlterTable
|
||||
-- Add the column with a temporary default of `true` so that all existing rows
|
||||
-- (representing organisations created before this feature) are backfilled to
|
||||
-- `true` — preserving the historical behaviour of creating personal
|
||||
-- organisations for SSO-provisioned users.
|
||||
ALTER TABLE "OrganisationAuthenticationPortal" ADD COLUMN "allowPersonalOrganisations" BOOLEAN NOT NULL DEFAULT true;
|
||||
|
||||
-- Switch the column default to `false` so that any organisations created from
|
||||
-- now on opt out of personal-organisation creation by default.
|
||||
ALTER TABLE "OrganisationAuthenticationPortal" ALTER COLUMN "allowPersonalOrganisations" SET DEFAULT false;
|
||||
@@ -1100,9 +1100,10 @@ model OrganisationAuthenticationPortal {
|
||||
clientSecret String @default("")
|
||||
wellKnownUrl String @default("")
|
||||
|
||||
defaultOrganisationRole OrganisationMemberRole @default(MEMBER)
|
||||
autoProvisionUsers Boolean @default(true)
|
||||
allowedDomains String[] @default([])
|
||||
defaultOrganisationRole OrganisationMemberRole @default(MEMBER)
|
||||
autoProvisionUsers Boolean @default(true)
|
||||
allowedDomains String[] @default([])
|
||||
allowPersonalOrganisations Boolean @default(false)
|
||||
}
|
||||
|
||||
model Counter {
|
||||
|
||||
@@ -52,6 +52,7 @@ export const getOrganisationAuthenticationPortal = async ({
|
||||
wellKnownUrl: true,
|
||||
autoProvisionUsers: true,
|
||||
allowedDomains: true,
|
||||
allowPersonalOrganisations: true,
|
||||
clientSecret: true,
|
||||
},
|
||||
},
|
||||
@@ -79,6 +80,7 @@ export const getOrganisationAuthenticationPortal = async ({
|
||||
wellKnownUrl: portal.wellKnownUrl,
|
||||
autoProvisionUsers: portal.autoProvisionUsers,
|
||||
allowedDomains: portal.allowedDomains,
|
||||
allowPersonalOrganisations: portal.allowPersonalOrganisations,
|
||||
clientSecretProvided: Boolean(portal.clientSecret),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export const ZGetOrganisationAuthenticationPortalResponseSchema =
|
||||
wellKnownUrl: true,
|
||||
autoProvisionUsers: true,
|
||||
allowedDomains: true,
|
||||
allowPersonalOrganisations: true,
|
||||
}).extend({
|
||||
/**
|
||||
* Whether we have the client secret in the database.
|
||||
|
||||
@@ -61,6 +61,7 @@ export const updateOrganisationAuthenticationPortalRoute = authenticatedProcedur
|
||||
wellKnownUrl,
|
||||
autoProvisionUsers,
|
||||
allowedDomains,
|
||||
allowPersonalOrganisations,
|
||||
} = data;
|
||||
|
||||
if (
|
||||
@@ -104,6 +105,7 @@ export const updateOrganisationAuthenticationPortalRoute = authenticatedProcedur
|
||||
wellKnownUrl,
|
||||
autoProvisionUsers,
|
||||
allowedDomains,
|
||||
allowPersonalOrganisations,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ export const ZUpdateOrganisationAuthenticationPortalRequestSchema = z.object({
|
||||
wellKnownUrl: z.union([z.string().url(), z.literal('')]),
|
||||
autoProvisionUsers: z.boolean(),
|
||||
allowedDomains: z.array(z.string().regex(domainRegex)),
|
||||
allowPersonalOrganisations: z.boolean(),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user