mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Add group deletion and (name) update support for SCIM integration
This commit is contained in:
@@ -260,7 +260,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/Groups",
|
url: "/Groups",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -284,22 +283,15 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log("create group");
|
|
||||||
console.log("create group req.body: ", req.body);
|
|
||||||
|
|
||||||
const group = await req.server.services.scim.createScimGroup({
|
const group = await req.server.services.scim.createScimGroup({
|
||||||
displayName: req.body.displayName,
|
displayName: req.body.displayName,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("create group resulting group: ", group);
|
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: GET /api/v1/scim/Groups/8432b0aa-93e0-4b55-af3c-cd3fcc176f81
|
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/Groups/:groupId",
|
url: "/Groups/:groupId",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -307,33 +299,93 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
params: z.object({
|
params: z.object({
|
||||||
groupId: z.string().trim()
|
groupId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
// body: z.object({
|
response: {
|
||||||
// schemas: z.array(z.string()),
|
200: z.object({
|
||||||
// Operations: z.array(
|
schemas: z.array(z.string()),
|
||||||
// z.object({
|
id: z.string().trim(),
|
||||||
// op: z.string().trim(),
|
displayName: z.string().trim(),
|
||||||
// path: z.string().trim().optional(),
|
members: z.array(
|
||||||
// value: z.union([
|
z.object({
|
||||||
// z.object({
|
value: z.string(),
|
||||||
// active: z.boolean()
|
display: z.string()
|
||||||
// }),
|
})
|
||||||
// z.string().trim()
|
),
|
||||||
// ])
|
meta: z.object({
|
||||||
// })
|
resourceType: z.string().trim()
|
||||||
// )
|
})
|
||||||
// }),
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const group = await req.server.services.scim.getScimGroup({
|
||||||
|
groupId: req.params.groupId,
|
||||||
|
orgId: req.permission.orgId
|
||||||
|
});
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/Groups/:groupId",
|
||||||
|
method: "PUT",
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
groupId: z.string().trim()
|
||||||
|
}),
|
||||||
|
body: z.object({
|
||||||
|
schemas: z.array(z.string()),
|
||||||
|
id: z.string().trim(),
|
||||||
|
displayName: z.string().trim(),
|
||||||
|
members: z.array(z.any()).length(0)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
schemas: z.array(z.string()),
|
||||||
|
id: z.string().trim(),
|
||||||
|
displayName: z.string().trim(),
|
||||||
|
members: z.array(
|
||||||
|
z.object({
|
||||||
|
value: z.string(),
|
||||||
|
display: z.string()
|
||||||
|
})
|
||||||
|
),
|
||||||
|
meta: z.object({
|
||||||
|
resourceType: z.string().trim()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const group = await req.server.services.scim.updateScimGroupName({
|
||||||
|
groupId: req.params.groupId,
|
||||||
|
orgId: req.permission.orgId,
|
||||||
|
displayName: req.body.displayName
|
||||||
|
});
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/Groups/:groupId",
|
||||||
|
method: "DELETE",
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
groupId: z.string().trim()
|
||||||
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({})
|
200: z.object({})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log("get scim group endpoint start");
|
const group = await req.server.services.scim.deleteScimGroup({
|
||||||
const group = await req.server.services.scim.getScimGroup({
|
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
});
|
});
|
||||||
console.log("get scim group endpoint end: ", group);
|
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
TCreateScimGroupDTO,
|
TCreateScimGroupDTO,
|
||||||
TCreateScimTokenDTO,
|
TCreateScimTokenDTO,
|
||||||
TCreateScimUserDTO,
|
TCreateScimUserDTO,
|
||||||
|
TDeleteScimGroupDTO,
|
||||||
TDeleteScimTokenDTO,
|
TDeleteScimTokenDTO,
|
||||||
TGetScimGroupDTO,
|
TGetScimGroupDTO,
|
||||||
TGetScimUserDTO,
|
TGetScimUserDTO,
|
||||||
@@ -32,6 +33,7 @@ import {
|
|||||||
TListScimUsersDTO,
|
TListScimUsersDTO,
|
||||||
TReplaceScimUserDTO,
|
TReplaceScimUserDTO,
|
||||||
TScimTokenJwtPayload,
|
TScimTokenJwtPayload,
|
||||||
|
TUpdateScimGroupNameDTO,
|
||||||
TUpdateScimUserDTO
|
TUpdateScimUserDTO
|
||||||
} from "./scim-types";
|
} from "./scim-types";
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ type TScimServiceFactoryDep = {
|
|||||||
>;
|
>;
|
||||||
projectDAL: Pick<TProjectDALFactory, "find">;
|
projectDAL: Pick<TProjectDALFactory, "find">;
|
||||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
|
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
|
||||||
groupDAL: Pick<TGroupDALFactory, "create" | "findOne" | "findAllGroupMembers">;
|
groupDAL: Pick<TGroupDALFactory, "create" | "findOne" | "findAllGroupMembers" | "update" | "delete">;
|
||||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
smtpService: TSmtpService;
|
smtpService: TSmtpService;
|
||||||
@@ -431,13 +433,6 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createScimGroup = async ({ displayName, orgId }: TCreateScimGroupDTO) => {
|
const createScimGroup = async ({ displayName, orgId }: TCreateScimGroupDTO) => {
|
||||||
// TODO 1: impl basic
|
|
||||||
// TODO 2: impl linking case
|
|
||||||
console.log("createScimGroup args: ", {
|
|
||||||
displayName,
|
|
||||||
orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
const group = await groupDAL.create({
|
const group = await groupDAL.create({
|
||||||
name: displayName,
|
name: displayName,
|
||||||
slug: slugify(`${displayName}-${alphaNumericNanoId(4)}`),
|
slug: slugify(`${displayName}-${alphaNumericNanoId(4)}`),
|
||||||
@@ -445,8 +440,6 @@ export const scimServiceFactory = ({
|
|||||||
role: OrgMembershipRole.NoAccess
|
role: OrgMembershipRole.NoAccess
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("createScimGroup the group: ", group);
|
|
||||||
|
|
||||||
return buildScimGroup({
|
return buildScimGroup({
|
||||||
groupId: group.id,
|
groupId: group.id,
|
||||||
name: group.name,
|
name: group.name,
|
||||||
@@ -455,21 +448,19 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getScimGroup = async ({ groupId, orgId }: TGetScimGroupDTO) => {
|
const getScimGroup = async ({ groupId, orgId }: TGetScimGroupDTO) => {
|
||||||
console.log("getScimGroup args: ", {
|
|
||||||
groupId,
|
|
||||||
orgId
|
|
||||||
});
|
|
||||||
|
|
||||||
const group = await groupDAL.findOne({
|
const group = await groupDAL.findOne({
|
||||||
id: groupId,
|
id: groupId,
|
||||||
orgId
|
orgId
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("getScimGroup group: ", group);
|
if (!group) {
|
||||||
const users = await groupDAL.findAllGroupMembers(group.orgId, group.id);
|
throw new ScimRequestError({
|
||||||
console.log("getScimGroup users: ", users);
|
detail: "Group Not Found",
|
||||||
|
status: 404
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: get members
|
const users = await groupDAL.findAllGroupMembers(group.orgId, group.id);
|
||||||
|
|
||||||
return buildScimGroup({
|
return buildScimGroup({
|
||||||
groupId: group.id,
|
groupId: group.id,
|
||||||
@@ -483,6 +474,47 @@ export const scimServiceFactory = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateScimGroupName = async ({ groupId, orgId, displayName }: TUpdateScimGroupNameDTO) => {
|
||||||
|
const [group] = await groupDAL.update(
|
||||||
|
{
|
||||||
|
id: groupId,
|
||||||
|
orgId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: displayName
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!group) {
|
||||||
|
throw new ScimRequestError({
|
||||||
|
detail: "Group Not Found",
|
||||||
|
status: 404
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildScimGroup({
|
||||||
|
groupId: group.id,
|
||||||
|
name: group.name,
|
||||||
|
members: []
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteScimGroup = async ({ groupId, orgId }: TDeleteScimGroupDTO) => {
|
||||||
|
const [group] = await groupDAL.delete({
|
||||||
|
id: groupId,
|
||||||
|
orgId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!group) {
|
||||||
|
throw new ScimRequestError({
|
||||||
|
detail: "Group Not Found",
|
||||||
|
status: 404
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {}; // intentionally return empty object upon success
|
||||||
|
};
|
||||||
|
|
||||||
const fnValidateScimToken = async (token: TScimTokenJwtPayload) => {
|
const fnValidateScimToken = async (token: TScimTokenJwtPayload) => {
|
||||||
const scimToken = await scimDAL.findById(token.scimTokenId);
|
const scimToken = await scimDAL.findById(token.scimTokenId);
|
||||||
if (!scimToken) throw new UnauthorizedError();
|
if (!scimToken) throw new UnauthorizedError();
|
||||||
@@ -517,6 +549,8 @@ export const scimServiceFactory = ({
|
|||||||
replaceScimUser,
|
replaceScimUser,
|
||||||
createScimGroup,
|
createScimGroup,
|
||||||
getScimGroup,
|
getScimGroup,
|
||||||
|
deleteScimGroup,
|
||||||
|
updateScimGroupName,
|
||||||
fnValidateScimToken
|
fnValidateScimToken
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -69,6 +69,17 @@ export type TGetScimGroupDTO = {
|
|||||||
orgId: string;
|
orgId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TUpdateScimGroupNameDTO = {
|
||||||
|
groupId: string;
|
||||||
|
orgId: string;
|
||||||
|
displayName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TDeleteScimGroupDTO = {
|
||||||
|
groupId: string;
|
||||||
|
orgId: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type TScimTokenJwtPayload = {
|
export type TScimTokenJwtPayload = {
|
||||||
scimTokenId: string;
|
scimTokenId: string;
|
||||||
authTokenType: string;
|
authTokenType: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user