Add group deletion and (name) update support for SCIM integration

This commit is contained in:
Tuan Dang
2024-04-05 10:13:47 -07:00
parent f7b8345da4
commit f8ea421a0e
3 changed files with 142 additions and 45 deletions

View File

@@ -260,7 +260,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
}
});
// TODO
server.route({
url: "/Groups",
method: "POST",
@@ -284,22 +283,15 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => {
console.log("create group");
console.log("create group req.body: ", req.body);
const group = await req.server.services.scim.createScimGroup({
displayName: req.body.displayName,
orgId: req.permission.orgId
});
console.log("create group resulting group: ", group);
return group;
}
});
// TODO: GET /api/v1/scim/Groups/8432b0aa-93e0-4b55-af3c-cd3fcc176f81
server.route({
url: "/Groups/:groupId",
method: "GET",
@@ -307,33 +299,93 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
params: z.object({
groupId: z.string().trim()
}),
// body: z.object({
// schemas: z.array(z.string()),
// Operations: z.array(
// z.object({
// op: z.string().trim(),
// path: z.string().trim().optional(),
// value: z.union([
// z.object({
// active: z.boolean()
// }),
// z.string().trim()
// ])
// })
// )
// }),
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.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: {
200: z.object({})
}
},
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
handler: async (req) => {
console.log("get scim group endpoint start");
const group = await req.server.services.scim.getScimGroup({
const group = await req.server.services.scim.deleteScimGroup({
groupId: req.params.groupId,
orgId: req.permission.orgId
});
console.log("get scim group endpoint end: ", group);
return group;
}
});

View File

@@ -25,6 +25,7 @@ import {
TCreateScimGroupDTO,
TCreateScimTokenDTO,
TCreateScimUserDTO,
TDeleteScimGroupDTO,
TDeleteScimTokenDTO,
TGetScimGroupDTO,
TGetScimUserDTO,
@@ -32,6 +33,7 @@ import {
TListScimUsersDTO,
TReplaceScimUserDTO,
TScimTokenJwtPayload,
TUpdateScimGroupNameDTO,
TUpdateScimUserDTO
} from "./scim-types";
@@ -44,7 +46,7 @@ type TScimServiceFactoryDep = {
>;
projectDAL: Pick<TProjectDALFactory, "find">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
groupDAL: Pick<TGroupDALFactory, "create" | "findOne" | "findAllGroupMembers">;
groupDAL: Pick<TGroupDALFactory, "create" | "findOne" | "findAllGroupMembers" | "update" | "delete">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
smtpService: TSmtpService;
@@ -431,13 +433,6 @@ export const scimServiceFactory = ({
};
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({
name: displayName,
slug: slugify(`${displayName}-${alphaNumericNanoId(4)}`),
@@ -445,8 +440,6 @@ export const scimServiceFactory = ({
role: OrgMembershipRole.NoAccess
});
console.log("createScimGroup the group: ", group);
return buildScimGroup({
groupId: group.id,
name: group.name,
@@ -455,21 +448,19 @@ export const scimServiceFactory = ({
};
const getScimGroup = async ({ groupId, orgId }: TGetScimGroupDTO) => {
console.log("getScimGroup args: ", {
groupId,
orgId
});
const group = await groupDAL.findOne({
id: groupId,
orgId
});
console.log("getScimGroup group: ", group);
const users = await groupDAL.findAllGroupMembers(group.orgId, group.id);
console.log("getScimGroup users: ", users);
if (!group) {
throw new ScimRequestError({
detail: "Group Not Found",
status: 404
});
}
// TODO: get members
const users = await groupDAL.findAllGroupMembers(group.orgId, group.id);
return buildScimGroup({
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 scimToken = await scimDAL.findById(token.scimTokenId);
if (!scimToken) throw new UnauthorizedError();
@@ -517,6 +549,8 @@ export const scimServiceFactory = ({
replaceScimUser,
createScimGroup,
getScimGroup,
deleteScimGroup,
updateScimGroupName,
fnValidateScimToken
};
};

View File

@@ -69,6 +69,17 @@ export type TGetScimGroupDTO = {
orgId: string;
};
export type TUpdateScimGroupNameDTO = {
groupId: string;
orgId: string;
displayName: string;
};
export type TDeleteScimGroupDTO = {
groupId: string;
orgId: string;
};
export type TScimTokenJwtPayload = {
scimTokenId: string;
authTokenType: string;