mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 04:27:29 +00:00
fix: resolved scim group update failing
This commit is contained in:
@@ -9,7 +9,10 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
server.addContentTypeParser("application/scim+json", { parseAs: "string" }, (_, body, done) => {
|
server.addContentTypeParser("application/scim+json", { parseAs: "string" }, (_, body, done) => {
|
||||||
try {
|
try {
|
||||||
const strBody = body instanceof Buffer ? body.toString() : body;
|
const strBody = body instanceof Buffer ? body.toString() : body;
|
||||||
|
if (!strBody) {
|
||||||
|
done(null, undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const json: unknown = JSON.parse(strBody);
|
const json: unknown = JSON.parse(strBody);
|
||||||
done(null, json);
|
done(null, json);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -474,18 +477,18 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
Operations: z.array(
|
Operations: z.array(
|
||||||
z.union([
|
z.union([
|
||||||
z.object({
|
z.object({
|
||||||
op: z.literal("replace"),
|
op: z.union([z.literal("replace"), z.literal("Replace")]),
|
||||||
value: z.object({
|
value: z.object({
|
||||||
id: z.string().trim(),
|
id: z.string().trim(),
|
||||||
displayName: z.string().trim()
|
displayName: z.string().trim()
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
op: z.literal("remove"),
|
op: z.union([z.literal("remove"), z.literal("Remove")]),
|
||||||
path: z.string().trim()
|
path: z.string().trim()
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
op: z.literal("add"),
|
op: z.union([z.literal("add"), z.literal("Add")]),
|
||||||
path: z.string().trim(),
|
path: z.string().trim(),
|
||||||
value: z.array(
|
value: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ export const buildScimUser = ({
|
|||||||
orgMembershipId: string;
|
orgMembershipId: string;
|
||||||
username: string;
|
username: string;
|
||||||
email?: string | null;
|
email?: string | null;
|
||||||
firstName: string;
|
firstName: string | null | undefined;
|
||||||
lastName: string;
|
lastName: string | null | undefined;
|
||||||
groups?: {
|
groups?: {
|
||||||
value: string;
|
value: string;
|
||||||
display: string;
|
display: string;
|
||||||
@@ -64,9 +64,9 @@ export const buildScimUser = ({
|
|||||||
userName: username,
|
userName: username,
|
||||||
displayName: `${firstName} ${lastName}`,
|
displayName: `${firstName} ${lastName}`,
|
||||||
name: {
|
name: {
|
||||||
givenName: firstName,
|
givenName: firstName || "",
|
||||||
middleName: null,
|
middleName: null,
|
||||||
familyName: lastName
|
familyName: lastName || ""
|
||||||
},
|
},
|
||||||
emails: email
|
emails: email
|
||||||
? [
|
? [
|
||||||
|
|||||||
@@ -267,8 +267,8 @@ export const scimServiceFactory = ({
|
|||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.externalId ?? membership.username,
|
username: membership.externalId ?? membership.username,
|
||||||
email: membership.email ?? "",
|
email: membership.email ?? "",
|
||||||
firstName: membership.firstName as string,
|
firstName: membership.firstName,
|
||||||
lastName: membership.lastName as string,
|
lastName: membership.lastName,
|
||||||
active: membership.isActive,
|
active: membership.isActive,
|
||||||
groups: groupMembershipsInOrg.map((group) => ({
|
groups: groupMembershipsInOrg.map((group) => ({
|
||||||
value: group.groupId,
|
value: group.groupId,
|
||||||
@@ -427,8 +427,8 @@ export const scimServiceFactory = ({
|
|||||||
return buildScimUser({
|
return buildScimUser({
|
||||||
orgMembershipId: createdOrgMembership.id,
|
orgMembershipId: createdOrgMembership.id,
|
||||||
username: externalId,
|
username: externalId,
|
||||||
firstName: createdUser.firstName as string,
|
firstName: createdUser.firstName,
|
||||||
lastName: createdUser.lastName as string,
|
lastName: createdUser.lastName,
|
||||||
email: createdUser.email ?? "",
|
email: createdUser.email ?? "",
|
||||||
active: createdOrgMembership.isActive
|
active: createdOrgMembership.isActive
|
||||||
});
|
});
|
||||||
@@ -483,8 +483,8 @@ export const scimServiceFactory = ({
|
|||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.externalId ?? membership.username,
|
username: membership.externalId ?? membership.username,
|
||||||
email: membership.email,
|
email: membership.email,
|
||||||
firstName: membership.firstName as string,
|
firstName: membership.firstName,
|
||||||
lastName: membership.lastName as string,
|
lastName: membership.lastName,
|
||||||
active
|
active
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -527,8 +527,8 @@ export const scimServiceFactory = ({
|
|||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.externalId ?? membership.username,
|
username: membership.externalId ?? membership.username,
|
||||||
email: membership.email,
|
email: membership.email,
|
||||||
firstName: membership.firstName as string,
|
firstName: membership.firstName,
|
||||||
lastName: membership.lastName as string,
|
lastName: membership.lastName,
|
||||||
active,
|
active,
|
||||||
groups: groupMembershipsInOrg.map((group) => ({
|
groups: groupMembershipsInOrg.map((group) => ({
|
||||||
value: group.groupId,
|
value: group.groupId,
|
||||||
@@ -884,59 +884,50 @@ export const scimServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
for await (const operation of operations) {
|
for await (const operation of operations) {
|
||||||
switch (operation.op) {
|
if (operation.op === "replace" || operation.op === "Replace") {
|
||||||
case "replace": {
|
group = await groupDAL.updateById(group.id, {
|
||||||
group = await groupDAL.updateById(group.id, {
|
name: operation.value.displayName
|
||||||
name: operation.value.displayName
|
});
|
||||||
|
} else if (operation.op === "add" || operation.op === "Add") {
|
||||||
|
try {
|
||||||
|
const orgMemberships = await orgMembershipDAL.find({
|
||||||
|
$in: {
|
||||||
|
id: operation.value.map((member) => member.value)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "add": {
|
|
||||||
try {
|
|
||||||
const orgMemberships = await orgMembershipDAL.find({
|
|
||||||
$in: {
|
|
||||||
id: operation.value.map((member) => member.value)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await addUsersToGroupByUserIds({
|
await addUsersToGroupByUserIds({
|
||||||
group,
|
|
||||||
userIds: orgMemberships.map((membership) => membership.userId as string),
|
|
||||||
userDAL,
|
|
||||||
userGroupMembershipDAL,
|
|
||||||
orgDAL,
|
|
||||||
groupProjectDAL,
|
|
||||||
projectKeyDAL,
|
|
||||||
projectDAL,
|
|
||||||
projectBotDAL
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
logger.info("Repeat SCIM user-group add operation");
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "remove": {
|
|
||||||
const orgMembershipId = extractScimValueFromPath(operation.path);
|
|
||||||
if (!orgMembershipId) throw new ScimRequestError({ detail: "Invalid path value", status: 400 });
|
|
||||||
const orgMembership = await orgMembershipDAL.findById(orgMembershipId);
|
|
||||||
if (!orgMembership) throw new ScimRequestError({ detail: "Org Membership Not Found", status: 400 });
|
|
||||||
await removeUsersFromGroupByUserIds({
|
|
||||||
group,
|
group,
|
||||||
userIds: [orgMembership.userId as string],
|
userIds: orgMemberships.map((membership) => membership.userId as string),
|
||||||
userDAL,
|
userDAL,
|
||||||
userGroupMembershipDAL,
|
userGroupMembershipDAL,
|
||||||
|
orgDAL,
|
||||||
groupProjectDAL,
|
groupProjectDAL,
|
||||||
projectKeyDAL
|
projectKeyDAL,
|
||||||
});
|
projectDAL,
|
||||||
break;
|
projectBotDAL
|
||||||
}
|
|
||||||
default: {
|
|
||||||
throw new ScimRequestError({
|
|
||||||
detail: "Invalid Operation",
|
|
||||||
status: 400
|
|
||||||
});
|
});
|
||||||
|
} catch {
|
||||||
|
logger.info("Repeat SCIM user-group add operation");
|
||||||
}
|
}
|
||||||
|
} else if (operation.op === "remove" || operation.op === "Remove") {
|
||||||
|
const orgMembershipId = extractScimValueFromPath(operation.path);
|
||||||
|
if (!orgMembershipId) throw new ScimRequestError({ detail: "Invalid path value", status: 400 });
|
||||||
|
const orgMembership = await orgMembershipDAL.findById(orgMembershipId);
|
||||||
|
if (!orgMembership) throw new ScimRequestError({ detail: "Org Membership Not Found", status: 400 });
|
||||||
|
await removeUsersFromGroupByUserIds({
|
||||||
|
group,
|
||||||
|
userIds: [orgMembership.userId as string],
|
||||||
|
userDAL,
|
||||||
|
userGroupMembershipDAL,
|
||||||
|
groupProjectDAL,
|
||||||
|
projectKeyDAL
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw new ScimRequestError({
|
||||||
|
detail: "Invalid Operation",
|
||||||
|
status: 400
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,8 +110,10 @@ export type TUpdateScimGroupNamePatchDTO = {
|
|||||||
operations: (TRemoveOp | TReplaceOp | TAddOp)[];
|
operations: (TRemoveOp | TReplaceOp | TAddOp)[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// akhilmhdh: I know, this is done due to lack of time. Need to change later to support as normalized rather than like this
|
||||||
|
// Forgive akhil blame tony
|
||||||
type TReplaceOp = {
|
type TReplaceOp = {
|
||||||
op: "replace";
|
op: "replace" | "Replace";
|
||||||
value: {
|
value: {
|
||||||
id: string;
|
id: string;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
@@ -119,12 +121,12 @@ type TReplaceOp = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type TRemoveOp = {
|
type TRemoveOp = {
|
||||||
op: "remove";
|
op: "remove" | "Remove";
|
||||||
path: string;
|
path: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TAddOp = {
|
type TAddOp = {
|
||||||
op: "add";
|
op: "add" | "Add";
|
||||||
path: string;
|
path: string;
|
||||||
value: {
|
value: {
|
||||||
value: string;
|
value: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user