Adjust SCIM and SAML impl to use username / nameID, patch LDAP edge-cases

This commit is contained in:
Tuan Dang
2024-02-25 18:16:26 -08:00
parent 8c31566e17
commit a33c50b75a
15 changed files with 136 additions and 82 deletions
+13 -9
View File
@@ -28,12 +28,12 @@ export const buildScimUser = ({
}: {
userId: string;
username: string;
email: string;
email?: string | null;
firstName: string;
lastName: string;
active: boolean;
}): TScimUser => {
return {
const scimUser = {
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
id: userId,
userName: username,
@@ -43,13 +43,15 @@ export const buildScimUser = ({
middleName: null,
familyName: lastName
},
emails: [
{
primary: true,
value: email,
type: "work"
}
],
emails: email
? [
{
primary: true,
value: email,
type: "work"
}
]
: [],
active,
groups: [],
meta: {
@@ -57,4 +59,6 @@ export const buildScimUser = ({
location: null
}
};
return scimUser;
};
+20 -15
View File
@@ -1,7 +1,7 @@
import { ForbiddenError } from "@casl/ability";
import jwt from "jsonwebtoken";
import { OrgMembershipRole, OrgMembershipStatus } from "@app/db/schemas";
import { OrgMembershipRole, OrgMembershipStatus, TableName } from "@app/db/schemas";
import { TScimDALFactory } from "@app/ee/services/scim/scim-dal";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, ScimRequestError, UnauthorizedError } from "@app/lib/errors";
@@ -146,7 +146,7 @@ export const scimServiceFactory = ({
const users = await orgDAL.findMembership(
{
orgId,
[`${TableName.OrgMembership}.orgId` as "id"]: orgId,
...parseFilter(filter)
},
findOpts
@@ -155,10 +155,10 @@ export const scimServiceFactory = ({
const scimUsers = users.map(({ userId, username, firstName, lastName, email }) =>
buildScimUser({
userId: userId ?? "",
username: username ?? "",
username,
firstName: firstName ?? "",
lastName: lastName ?? "",
email: email ?? "",
email,
active: true
})
);
@@ -174,7 +174,7 @@ export const scimServiceFactory = ({
const [membership] = await orgDAL
.findMembership({
userId,
orgId
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
})
.catch(() => {
throw new ScimRequestError({
@@ -205,8 +205,7 @@ export const scimServiceFactory = ({
});
};
// TODO: update SCIM endpoints to add username
const createScimUser = async ({ firstName, lastName, email, orgId }: TCreateScimUserDTO) => {
const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => {
const org = await orgDAL.findById(orgId);
if (!org)
@@ -222,12 +221,18 @@ export const scimServiceFactory = ({
});
let user = await userDAL.findOne({
email
username
});
if (user) {
await userDAL.transaction(async (tx) => {
const [orgMembership] = await orgDAL.findMembership({ userId: user.id, orgId }, { tx });
const [orgMembership] = await orgDAL.findMembership(
{
userId: user.id,
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
},
{ tx }
);
if (orgMembership)
throw new ScimRequestError({
detail: "User already exists in the database",
@@ -251,7 +256,7 @@ export const scimServiceFactory = ({
user = await userDAL.transaction(async (tx) => {
const newUser = await userDAL.create(
{
username: email,
username,
email,
firstName,
lastName,
@@ -279,7 +284,7 @@ export const scimServiceFactory = ({
await smtpService.sendMail({
template: SmtpTemplates.ScimUserProvisioned,
subjectLine: "Infisical organization invitation",
recipients: [email],
recipients: email ? [email] : [],
substitutions: {
organizationName: org.name,
callback_url: `${appCfg.SITE_URL}/api/v1/sso/redirect/saml2/organizations/${org.slug}`
@@ -300,7 +305,7 @@ export const scimServiceFactory = ({
const [membership] = await orgDAL
.findMembership({
userId,
orgId
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
})
.catch(() => {
throw new ScimRequestError({
@@ -348,7 +353,7 @@ export const scimServiceFactory = ({
return buildScimUser({
userId: membership.userId as string,
username: membership.username,
email: membership.email ?? "",
email: membership.email,
firstName: membership.firstName as string,
lastName: membership.lastName as string,
active
@@ -359,7 +364,7 @@ export const scimServiceFactory = ({
const [membership] = await orgDAL
.findMembership({
userId,
orgId
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
})
.catch(() => {
throw new ScimRequestError({
@@ -394,7 +399,7 @@ export const scimServiceFactory = ({
return buildScimUser({
userId: membership.userId as string,
username: membership.username,
email: membership.email ?? "",
email: membership.email,
firstName: membership.firstName as string,
lastName: membership.lastName as string,
active
+2 -1
View File
@@ -32,7 +32,8 @@ export type TGetScimUserDTO = {
};
export type TCreateScimUserDTO = {
email: string;
username: string;
email?: string;
firstName: string;
lastName: string;
orgId: string;