mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 08:26:10 +00:00
Update groups CRUD SCIM to use orgMembershipId
This commit is contained in:
@@ -152,7 +152,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log("GET /Users req.query: ", req.query);
|
|
||||||
const users = await req.server.services.scim.listScimUsers({
|
const users = await req.server.services.scim.listScimUsers({
|
||||||
startIndex: req.query.startIndex,
|
startIndex: req.query.startIndex,
|
||||||
limit: req.query.count,
|
limit: req.query.count,
|
||||||
@@ -193,7 +192,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`GET /Users/${req.params.orgMembershipId}`);
|
|
||||||
const user = await req.server.services.scim.getScimUser({
|
const user = await req.server.services.scim.getScimUser({
|
||||||
orgMembershipId: req.params.orgMembershipId,
|
orgMembershipId: req.params.orgMembershipId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -248,8 +246,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log("POST /Users req.body: ", req.body);
|
|
||||||
|
|
||||||
const primaryEmail = req.body.emails?.find((email) => email.primary)?.value;
|
const primaryEmail = req.body.emails?.find((email) => email.primary)?.value;
|
||||||
|
|
||||||
const user = await req.server.services.scim.createScimUser({
|
const user = await req.server.services.scim.createScimUser({
|
||||||
@@ -277,7 +273,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`DELETE /Users/${req.params.orgMembershipId}`);
|
|
||||||
const user = await req.server.services.scim.deleteScimUser({
|
const user = await req.server.services.scim.deleteScimUser({
|
||||||
orgMembershipId: req.params.orgMembershipId,
|
orgMembershipId: req.params.orgMembershipId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -324,7 +319,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log("POST /Groups req.body: ", req.body);
|
|
||||||
const group = await req.server.services.scim.createScimGroup({
|
const group = await req.server.services.scim.createScimGroup({
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
...req.body
|
...req.body
|
||||||
@@ -365,10 +359,9 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log("GET /Groups req.query: ", req.query);
|
|
||||||
const groups = await req.server.services.scim.listScimGroups({
|
const groups = await req.server.services.scim.listScimGroups({
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
offset: req.query.startIndex,
|
startIndex: req.query.startIndex,
|
||||||
limit: req.query.count
|
limit: req.query.count
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -402,7 +395,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`GET /Groups/${req.params.groupId}`);
|
|
||||||
const group = await req.server.services.scim.getScimGroup({
|
const group = await req.server.services.scim.getScimGroup({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -424,10 +416,10 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
displayName: z.string().trim(),
|
displayName: z.string().trim(),
|
||||||
members: z.array(
|
members: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
value: z.string(), // infisical userId
|
value: z.string(), // infisical orgMembershipId
|
||||||
display: z.string()
|
display: z.string()
|
||||||
})
|
})
|
||||||
) // note: is this where members are added to group?
|
)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -448,7 +440,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`PUT /Groups/${req.params.groupId} req.body: `, req.body);
|
|
||||||
const group = await req.server.services.scim.updateScimGroupNamePut({
|
const group = await req.server.services.scim.updateScimGroupNamePut({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
@@ -510,7 +501,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`PATCH /Groups/${req.params.groupId} req.body: `, req.body);
|
|
||||||
const group = await req.server.services.scim.updateScimGroupNamePatch({
|
const group = await req.server.services.scim.updateScimGroupNamePatch({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
@@ -534,7 +524,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`DELETE /Groups/${req.params.groupId}`);
|
|
||||||
const group = await req.server.services.scim.deleteScimGroup({
|
const group = await req.server.services.scim.deleteScimGroup({
|
||||||
groupId: req.params.groupId,
|
groupId: req.params.groupId,
|
||||||
orgId: req.permission.orgId
|
orgId: req.permission.orgId
|
||||||
@@ -585,7 +574,6 @@ export const registerScimRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
onRequest: verifyAuth([AuthMode.SCIM_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
console.log(`PUT /Users/${req.params.orgMembershipId} req.body: `, req.body);
|
|
||||||
const user = await req.server.services.scim.replaceScimUser({
|
const user = await req.server.services.scim.replaceScimUser({
|
||||||
orgMembershipId: req.params.orgMembershipId,
|
orgMembershipId: req.params.orgMembershipId,
|
||||||
orgId: req.permission.orgId,
|
orgId: req.permission.orgId,
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ export const samlConfigServiceFactory = ({
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
user = await userDAL.transaction(async (tx) => {
|
user = await userDAL.transaction(async (tx) => {
|
||||||
const uniqueUsername = await normalizeUsername(externalId, userDAL);
|
const uniqueUsername = await normalizeUsername(`${firstName ?? ""}-${lastName ?? ""}`, userDAL);
|
||||||
const newUser = await userDAL.create(
|
const newUser = await userDAL.create(
|
||||||
{
|
{
|
||||||
username: uniqueUsername,
|
username: uniqueUsername,
|
||||||
|
|||||||
@@ -65,18 +65,18 @@ export const buildScimUser = ({
|
|||||||
|
|
||||||
export const buildScimGroupList = ({
|
export const buildScimGroupList = ({
|
||||||
scimGroups,
|
scimGroups,
|
||||||
offset,
|
startIndex,
|
||||||
limit
|
limit
|
||||||
}: {
|
}: {
|
||||||
scimGroups: TScimGroup[];
|
scimGroups: TScimGroup[];
|
||||||
offset: number;
|
startIndex: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
}): TListScimGroups => {
|
}): TListScimGroups => {
|
||||||
return {
|
return {
|
||||||
Resources: scimGroups,
|
Resources: scimGroups,
|
||||||
itemsPerPage: limit,
|
itemsPerPage: limit,
|
||||||
schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
|
schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
|
||||||
startIndex: offset,
|
startIndex,
|
||||||
totalResults: scimGroups.length
|
totalResults: scimGroups.length
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { TOrgPermission } from "@app/lib/types";
|
|||||||
import { AuthTokenType } from "@app/services/auth/auth-type";
|
import { AuthTokenType } from "@app/services/auth/auth-type";
|
||||||
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
|
||||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||||
import { deleteOrgMembership } from "@app/services/org/org-fns";
|
import { deleteOrgMembershipFn } from "@app/services/org/org-fns";
|
||||||
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
|
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
|
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
|
||||||
@@ -62,7 +62,7 @@ type TScimServiceFactoryDep = {
|
|||||||
>;
|
>;
|
||||||
orgMembershipDAL: TOrgMembershipDALFactory; // TODO: Pick
|
orgMembershipDAL: TOrgMembershipDALFactory; // TODO: Pick
|
||||||
projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser">;
|
projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser">;
|
||||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
|
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete" | "findProjectMembershipsByUserId">;
|
||||||
groupDAL: Pick<
|
groupDAL: Pick<
|
||||||
TGroupDALFactory,
|
TGroupDALFactory,
|
||||||
"create" | "findOne" | "findAllGroupMembers" | "update" | "delete" | "findGroups" | "transaction"
|
"create" | "findOne" | "findAllGroupMembers" | "update" | "delete" | "findGroups" | "transaction"
|
||||||
@@ -71,7 +71,7 @@ type TScimServiceFactoryDep = {
|
|||||||
userGroupMembershipDAL: TUserGroupMembershipDALFactory; // TODO: Pick
|
userGroupMembershipDAL: TUserGroupMembershipDALFactory; // TODO: Pick
|
||||||
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "findLatestProjectKey" | "insertMany" | "delete">;
|
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "findLatestProjectKey" | "insertMany" | "delete">;
|
||||||
projectBotDAL: Pick<TProjectBotDALFactory, "findOne">;
|
projectBotDAL: Pick<TProjectBotDALFactory, "findOne">;
|
||||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
smtpService: Pick<TSmtpService, "sendMail">;
|
smtpService: Pick<TSmtpService, "sendMail">;
|
||||||
};
|
};
|
||||||
@@ -174,12 +174,6 @@ export const scimServiceFactory = ({
|
|||||||
|
|
||||||
// SCIM server endpoints
|
// SCIM server endpoints
|
||||||
const listScimUsers = async ({ startIndex, limit, filter, orgId }: TListScimUsersDTO): Promise<TListScimUsers> => {
|
const listScimUsers = async ({ startIndex, limit, filter, orgId }: TListScimUsersDTO): Promise<TListScimUsers> => {
|
||||||
console.log("listScimUsers args: ", {
|
|
||||||
startIndex,
|
|
||||||
limit,
|
|
||||||
filter,
|
|
||||||
orgId
|
|
||||||
}); // done
|
|
||||||
const org = await orgDAL.findById(orgId);
|
const org = await orgDAL.findById(orgId);
|
||||||
|
|
||||||
if (!org.scimEnabled)
|
if (!org.scimEnabled)
|
||||||
@@ -232,10 +226,6 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getScimUser = async ({ orgMembershipId, orgId }: TGetScimUserDTO) => {
|
const getScimUser = async ({ orgMembershipId, orgId }: TGetScimUserDTO) => {
|
||||||
console.log("getScimUser args: ", {
|
|
||||||
orgMembershipId,
|
|
||||||
orgId
|
|
||||||
}); // done
|
|
||||||
const [membership] = await orgDAL
|
const [membership] = await orgDAL
|
||||||
.findMembership({
|
.findMembership({
|
||||||
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
||||||
@@ -260,8 +250,6 @@ export const scimServiceFactory = ({
|
|||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("getScimUser membership: ", membership);
|
|
||||||
|
|
||||||
return buildScimUser({
|
return buildScimUser({
|
||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
username: membership.username,
|
username: membership.username,
|
||||||
@@ -273,14 +261,6 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => {
|
const createScimUser = async ({ username, email, firstName, lastName, orgId }: TCreateScimUserDTO) => {
|
||||||
// do we get external ID or not?
|
|
||||||
console.log("createScimUser args: ", {
|
|
||||||
username,
|
|
||||||
email,
|
|
||||||
firstName,
|
|
||||||
lastName,
|
|
||||||
orgId
|
|
||||||
});
|
|
||||||
const org = await orgDAL.findById(orgId);
|
const org = await orgDAL.findById(orgId);
|
||||||
|
|
||||||
if (!org)
|
if (!org)
|
||||||
@@ -337,7 +317,7 @@ export const scimServiceFactory = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const uniqueUsername = await normalizeUsername(username, userDAL);
|
const uniqueUsername = await normalizeUsername(`${firstName}-${lastName}`, userDAL);
|
||||||
user = await userDAL.create(
|
user = await userDAL.create(
|
||||||
{
|
{
|
||||||
username: uniqueUsername,
|
username: uniqueUsername,
|
||||||
@@ -398,7 +378,6 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateScimUser = async ({ userId, orgId, operations }: TUpdateScimUserDTO) => {
|
const updateScimUser = async ({ userId, orgId, operations }: TUpdateScimUserDTO) => {
|
||||||
console.log("updateScimUser"); // done
|
|
||||||
const [membership] = await orgDAL
|
const [membership] = await orgDAL
|
||||||
.findMembership({
|
.findMembership({
|
||||||
userId,
|
userId,
|
||||||
@@ -438,12 +417,14 @@ export const scimServiceFactory = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
await deleteOrgMembership({
|
await deleteOrgMembershipFn({
|
||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
orgId: membership.orgId,
|
orgId: membership.orgId,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
projectDAL,
|
projectMembershipDAL,
|
||||||
projectMembershipDAL
|
projectKeyDAL,
|
||||||
|
userAliasDAL,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,11 +439,6 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const replaceScimUser = async ({ orgMembershipId, active, orgId }: TReplaceScimUserDTO) => {
|
const replaceScimUser = async ({ orgMembershipId, active, orgId }: TReplaceScimUserDTO) => {
|
||||||
console.log("replaceScimUser args: ", {
|
|
||||||
orgMembershipId,
|
|
||||||
orgId,
|
|
||||||
active
|
|
||||||
}); // done
|
|
||||||
const [membership] = await orgDAL
|
const [membership] = await orgDAL
|
||||||
.findMembership({
|
.findMembership({
|
||||||
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
||||||
@@ -489,12 +465,14 @@ export const scimServiceFactory = ({
|
|||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
// tx
|
// tx
|
||||||
await deleteOrgMembership({
|
await deleteOrgMembershipFn({
|
||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
orgId: membership.orgId,
|
orgId: membership.orgId,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
projectDAL,
|
projectMembershipDAL,
|
||||||
projectMembershipDAL
|
projectKeyDAL,
|
||||||
|
userAliasDAL,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,10 +487,6 @@ export const scimServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const deleteScimUser = async ({ orgMembershipId, orgId }: TDeleteScimUserDTO) => {
|
const deleteScimUser = async ({ orgMembershipId, orgId }: TDeleteScimUserDTO) => {
|
||||||
console.log("deleteScimUser args: ", {
|
|
||||||
orgMembershipId,
|
|
||||||
orgId
|
|
||||||
}); // done
|
|
||||||
const [membership] = await orgDAL.findMembership({
|
const [membership] = await orgDAL.findMembership({
|
||||||
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
|
||||||
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
|
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
|
||||||
@@ -531,18 +505,20 @@ export const scimServiceFactory = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await deleteOrgMembership({
|
await deleteOrgMembershipFn({
|
||||||
orgMembershipId: membership.id,
|
orgMembershipId: membership.id,
|
||||||
orgId: membership.orgId,
|
orgId: membership.orgId,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
projectDAL,
|
projectMembershipDAL,
|
||||||
projectMembershipDAL
|
projectKeyDAL,
|
||||||
|
userAliasDAL,
|
||||||
|
licenseService
|
||||||
});
|
});
|
||||||
|
|
||||||
return {}; // intentionally return empty object upon success
|
return {}; // intentionally return empty object upon success
|
||||||
};
|
};
|
||||||
|
|
||||||
const listScimGroups = async ({ orgId, offset, limit }: TListScimGroupsDTO) => {
|
const listScimGroups = async ({ orgId, startIndex, limit }: TListScimGroupsDTO) => {
|
||||||
const plan = await licenseService.getPlan(orgId);
|
const plan = await licenseService.getPlan(orgId);
|
||||||
if (!plan.groups)
|
if (!plan.groups)
|
||||||
throw new BadRequestError({
|
throw new BadRequestError({
|
||||||
@@ -563,9 +539,15 @@ export const scimServiceFactory = ({
|
|||||||
status: 403
|
status: 403
|
||||||
});
|
});
|
||||||
|
|
||||||
const groups = await groupDAL.findGroups({
|
const groups = await groupDAL.findGroups(
|
||||||
orgId
|
{
|
||||||
});
|
orgId
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: startIndex - 1,
|
||||||
|
limit
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const scimGroups = groups.map((group) =>
|
const scimGroups = groups.map((group) =>
|
||||||
buildScimGroup({
|
buildScimGroup({
|
||||||
@@ -577,7 +559,7 @@ export const scimServiceFactory = ({
|
|||||||
|
|
||||||
return buildScimGroupList({
|
return buildScimGroupList({
|
||||||
scimGroups,
|
scimGroups,
|
||||||
offset,
|
startIndex,
|
||||||
limit
|
limit
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -616,9 +598,15 @@ export const scimServiceFactory = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (members && members.length) {
|
if (members && members.length) {
|
||||||
|
const orgMemberships = await orgMembershipDAL.find({
|
||||||
|
$in: {
|
||||||
|
id: members.map((member) => member.value)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const newMembers = await addUsersToGroupByUserIds({
|
const newMembers = await addUsersToGroupByUserIds({
|
||||||
group,
|
group,
|
||||||
userIds: members.map((member) => member.value),
|
userIds: orgMemberships.map((membership) => membership.userId as string),
|
||||||
userDAL,
|
userDAL,
|
||||||
userGroupMembershipDAL,
|
userGroupMembershipDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
@@ -733,7 +721,13 @@ export const scimServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (members) {
|
if (members) {
|
||||||
const membersIdsSet = new Set(members.map((member) => member.value));
|
const orgMemberships = await orgMembershipDAL.find({
|
||||||
|
$in: {
|
||||||
|
id: members.map((member) => member.value)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const membersIdsSet = new Set(orgMemberships.map((orgMembership) => orgMembership.userId));
|
||||||
|
|
||||||
const directMemberUserIds = (
|
const directMemberUserIds = (
|
||||||
await userGroupMembershipDAL.find({
|
await userGroupMembershipDAL.find({
|
||||||
@@ -752,13 +746,13 @@ export const scimServiceFactory = ({
|
|||||||
const allMembersUserIds = directMemberUserIds.concat(pendingGroupAdditionsUserIds);
|
const allMembersUserIds = directMemberUserIds.concat(pendingGroupAdditionsUserIds);
|
||||||
const allMembersUserIdsSet = new Set(allMembersUserIds);
|
const allMembersUserIdsSet = new Set(allMembersUserIds);
|
||||||
|
|
||||||
const toAddUserIds = members.filter((member) => !allMembersUserIdsSet.has(member.value));
|
const toAddUserIds = orgMemberships.filter((member) => !allMembersUserIdsSet.has(member.userId as string));
|
||||||
const toRemoveUserIds = allMembersUserIds.filter((userId) => !membersIdsSet.has(userId));
|
const toRemoveUserIds = allMembersUserIds.filter((userId) => !membersIdsSet.has(userId));
|
||||||
|
|
||||||
if (toAddUserIds.length) {
|
if (toAddUserIds.length) {
|
||||||
await addUsersToGroupByUserIds({
|
await addUsersToGroupByUserIds({
|
||||||
group,
|
group,
|
||||||
userIds: toAddUserIds.map((member) => member.value),
|
userIds: toAddUserIds.map((member) => member.userId as string),
|
||||||
userDAL,
|
userDAL,
|
||||||
userGroupMembershipDAL,
|
userGroupMembershipDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export type TDeleteScimUserDTO = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type TListScimGroupsDTO = {
|
export type TListScimGroupsDTO = {
|
||||||
offset: number;
|
startIndex: number;
|
||||||
limit: number;
|
limit: number;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -349,6 +349,7 @@ export const registerRoutes = async (
|
|||||||
userDAL
|
userDAL
|
||||||
});
|
});
|
||||||
const orgService = orgServiceFactory({
|
const orgService = orgServiceFactory({
|
||||||
|
userAliasDAL,
|
||||||
licenseService,
|
licenseService,
|
||||||
samlConfigDAL,
|
samlConfigDAL,
|
||||||
orgRoleDAL,
|
orgRoleDAL,
|
||||||
|
|||||||
@@ -1,43 +1,78 @@
|
|||||||
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
import { TOrgDALFactory } from "@app/services/org/org-dal";
|
||||||
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
|
||||||
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
import { TProjectMembershipDALFactory } from "@app/services/project-membership/project-membership-dal";
|
||||||
|
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
||||||
|
|
||||||
type TDeleteOrgMembership = {
|
type TDeleteOrgMembership = {
|
||||||
orgMembershipId: string;
|
orgMembershipId: string;
|
||||||
orgId: string;
|
orgId: string;
|
||||||
orgDAL: Pick<TOrgDALFactory, "findMembership" | "deleteMembershipById" | "transaction">;
|
orgDAL: Pick<TOrgDALFactory, "findMembership" | "deleteMembershipById" | "transaction">;
|
||||||
projectDAL: Pick<TProjectDALFactory, "find">;
|
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "delete" | "findProjectMembershipsByUserId">;
|
||||||
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete">;
|
projectKeyDAL: Pick<TProjectKeyDALFactory, "find" | "delete">;
|
||||||
|
userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "updateSubscriptionOrgMemberCount">;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deleteOrgMembership = async ({
|
export const deleteOrgMembershipFn = async ({
|
||||||
orgMembershipId,
|
orgMembershipId,
|
||||||
orgId,
|
orgId,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
projectDAL,
|
projectMembershipDAL,
|
||||||
projectMembershipDAL
|
projectKeyDAL,
|
||||||
|
userAliasDAL,
|
||||||
|
licenseService
|
||||||
}: TDeleteOrgMembership) => {
|
}: TDeleteOrgMembership) => {
|
||||||
const membership = await orgDAL.transaction(async (tx) => {
|
const deletedMembership = await orgDAL.transaction(async (tx) => {
|
||||||
// delete org membership
|
|
||||||
const orgMembership = await orgDAL.deleteMembershipById(orgMembershipId, orgId, tx);
|
const orgMembership = await orgDAL.deleteMembershipById(orgMembershipId, orgId, tx);
|
||||||
|
|
||||||
const projects = await projectDAL.find({ orgId }, { tx });
|
if (!orgMembership.userId) {
|
||||||
|
await licenseService.updateSubscriptionOrgMemberCount(orgId);
|
||||||
|
return orgMembership;
|
||||||
|
}
|
||||||
|
|
||||||
// delete associated project memberships
|
await userAliasDAL.delete(
|
||||||
await projectMembershipDAL.delete(
|
|
||||||
{
|
{
|
||||||
$in: {
|
userId: orgMembership.userId,
|
||||||
projectId: projects.map((project) => project.id)
|
orgId
|
||||||
},
|
|
||||||
userId: orgMembership.userId as string
|
|
||||||
},
|
},
|
||||||
tx
|
tx
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: delete associated aliases
|
// Get all the project memberships of the user in the organization
|
||||||
|
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, orgMembership.userId);
|
||||||
|
|
||||||
|
// Delete all the project memberships of the user in the organization
|
||||||
|
await projectMembershipDAL.delete(
|
||||||
|
{
|
||||||
|
$in: {
|
||||||
|
id: projectMemberships.map((membership) => membership.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get all the project keys of the user in the organization
|
||||||
|
const projectKeys = await projectKeyDAL.find({
|
||||||
|
$in: {
|
||||||
|
projectId: projectMemberships.map((membership) => membership.projectId)
|
||||||
|
},
|
||||||
|
receiverId: orgMembership.userId
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete all the project keys of the user in the organization
|
||||||
|
await projectKeyDAL.delete(
|
||||||
|
{
|
||||||
|
$in: {
|
||||||
|
id: projectKeys.map((key) => key.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
|
||||||
|
await licenseService.updateSubscriptionOrgMemberCount(orgId);
|
||||||
return orgMembership;
|
return orgMembership;
|
||||||
});
|
});
|
||||||
|
|
||||||
return membership;
|
return deletedMembership;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { generateUserSrpKeys } from "@app/lib/crypto/srp";
|
|||||||
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { isDisposableEmail } from "@app/lib/validator";
|
import { isDisposableEmail } from "@app/lib/validator";
|
||||||
|
import { TUserAliasDALFactory } from "@app/services/user-alias/user-alias-dal";
|
||||||
|
|
||||||
import { ActorAuthMethod, ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type";
|
import { ActorAuthMethod, ActorType, AuthMethod, AuthTokenType } from "../auth/auth-type";
|
||||||
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
|
import { TAuthTokenServiceFactory } from "../auth-token/auth-token-service";
|
||||||
@@ -30,6 +31,7 @@ import { TUserDALFactory } from "../user/user-dal";
|
|||||||
import { TIncidentContactsDALFactory } from "./incident-contacts-dal";
|
import { TIncidentContactsDALFactory } from "./incident-contacts-dal";
|
||||||
import { TOrgBotDALFactory } from "./org-bot-dal";
|
import { TOrgBotDALFactory } from "./org-bot-dal";
|
||||||
import { TOrgDALFactory } from "./org-dal";
|
import { TOrgDALFactory } from "./org-dal";
|
||||||
|
import { deleteOrgMembershipFn } from "./org-fns";
|
||||||
import { TOrgRoleDALFactory } from "./org-role-dal";
|
import { TOrgRoleDALFactory } from "./org-role-dal";
|
||||||
import {
|
import {
|
||||||
TDeleteOrgMembershipDTO,
|
TDeleteOrgMembershipDTO,
|
||||||
@@ -43,6 +45,7 @@ import {
|
|||||||
} from "./org-types";
|
} from "./org-types";
|
||||||
|
|
||||||
type TOrgServiceFactoryDep = {
|
type TOrgServiceFactoryDep = {
|
||||||
|
userAliasDAL: Pick<TUserAliasDALFactory, "delete">;
|
||||||
orgDAL: TOrgDALFactory;
|
orgDAL: TOrgDALFactory;
|
||||||
orgBotDAL: TOrgBotDALFactory;
|
orgBotDAL: TOrgBotDALFactory;
|
||||||
orgRoleDAL: TOrgRoleDALFactory;
|
orgRoleDAL: TOrgRoleDALFactory;
|
||||||
@@ -65,6 +68,7 @@ type TOrgServiceFactoryDep = {
|
|||||||
export type TOrgServiceFactory = ReturnType<typeof orgServiceFactory>;
|
export type TOrgServiceFactory = ReturnType<typeof orgServiceFactory>;
|
||||||
|
|
||||||
export const orgServiceFactory = ({
|
export const orgServiceFactory = ({
|
||||||
|
userAliasDAL,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
userDAL,
|
userDAL,
|
||||||
groupDAL,
|
groupDAL,
|
||||||
@@ -572,47 +576,14 @@ export const orgServiceFactory = ({
|
|||||||
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
|
const { permission } = await permissionService.getUserOrgPermission(userId, orgId, actorAuthMethod, actorOrgId);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Member);
|
||||||
|
|
||||||
const deletedMembership = await orgDAL.transaction(async (tx) => {
|
const deletedMembership = await deleteOrgMembershipFn({
|
||||||
const orgMembership = await orgDAL.deleteMembershipById(membershipId, orgId, tx);
|
orgMembershipId: membershipId,
|
||||||
|
orgId,
|
||||||
if (!orgMembership.userId) {
|
orgDAL,
|
||||||
await licenseService.updateSubscriptionOrgMemberCount(orgId);
|
projectMembershipDAL,
|
||||||
return orgMembership;
|
projectKeyDAL,
|
||||||
}
|
userAliasDAL,
|
||||||
|
licenseService
|
||||||
// Get all the project memberships of the user in the organization
|
|
||||||
const projectMemberships = await projectMembershipDAL.findProjectMembershipsByUserId(orgId, orgMembership.userId);
|
|
||||||
|
|
||||||
// Delete all the project memberships of the user in the organization
|
|
||||||
await projectMembershipDAL.delete(
|
|
||||||
{
|
|
||||||
$in: {
|
|
||||||
id: projectMemberships.map((membership) => membership.id)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tx
|
|
||||||
);
|
|
||||||
|
|
||||||
// Get all the project keys of the user in the organization
|
|
||||||
const projectKeys = await projectKeyDAL.find({
|
|
||||||
$in: {
|
|
||||||
projectId: projectMemberships.map((membership) => membership.projectId)
|
|
||||||
},
|
|
||||||
receiverId: orgMembership.userId
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete all the project keys of the user in the organization
|
|
||||||
await projectKeyDAL.delete(
|
|
||||||
{
|
|
||||||
$in: {
|
|
||||||
id: projectKeys.map((key) => key.id)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tx
|
|
||||||
);
|
|
||||||
|
|
||||||
await licenseService.updateSubscriptionOrgMemberCount(orgId);
|
|
||||||
return orgMembership;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return deletedMembership;
|
return deletedMembership;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { alphaNumericNanoId } from "@app/lib/nanoid";
|
|||||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
|
|
||||||
export const normalizeUsername = async (username: string, userDAL: Pick<TUserDALFactory, "findOne">) => {
|
export const normalizeUsername = async (username: string, userDAL: Pick<TUserDALFactory, "findOne">) => {
|
||||||
let attempt = slugify(username);
|
let attempt = slugify(`${username}-${alphaNumericNanoId(4)}`);
|
||||||
|
|
||||||
let user = await userDAL.findOne({ username: attempt });
|
let user = await userDAL.findOne({ username: attempt });
|
||||||
if (!user) return attempt;
|
if (!user) return attempt;
|
||||||
|
|||||||
Reference in New Issue
Block a user