feat: fixing ts

This commit is contained in:
=
2025-10-10 00:09:45 +05:30
parent 0ddf98ec15
commit 5a8bad3556
38 changed files with 716 additions and 2437 deletions
+96 -68
View File
@@ -2,7 +2,15 @@ import { ForbiddenError } from "@casl/ability";
import slugify from "@sindresorhus/slugify";
import { scimPatch } from "scim-patch";
import { OrgMembershipRole, OrgMembershipStatus, TableName, TGroups, TOrgMemberships, TUsers } from "@app/db/schemas";
import {
AccessScope,
OrgMembershipRole,
OrgMembershipStatus,
TableName,
TGroups,
TMemberships,
TUsers
} from "@app/db/schemas";
import { TGroupDALFactory } from "@app/ee/services/group/group-dal";
import { addUsersToGroupByUserIds, removeUsersFromGroupByUserIds } from "@app/ee/services/group/group-fns";
import { TUserGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
@@ -13,12 +21,13 @@ import { BadRequestError, NotFoundError, ScimRequestError, UnauthorizedError } f
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { AuthTokenType } from "@app/services/auth/auth-type";
import { TExternalGroupOrgRoleMappingDALFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-dal";
import { TGroupProjectDALFactory } from "@app/services/group-project/group-project-dal";
import { TMembershipRoleDALFactory } from "@app/services/membership/membership-role-dal";
import { TMembershipGroupDALFactory } from "@app/services/membership-group/membership-group-dal";
import { TMembershipUserDALFactory } from "@app/services/membership-user/membership-user-dal";
import { TOrgDALFactory } from "@app/services/org/org-dal";
import { deleteOrgMembershipFn } from "@app/services/org/org-fns";
import { getDefaultOrgMembershipRole } from "@app/services/org/org-role-fns";
import { OrgAuthMethod } from "@app/services/org/org-types";
import { TOrgMembershipDALFactory } from "@app/services/org-membership/org-membership-dal";
import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TProjectBotDALFactory } from "@app/services/project-bot/project-bot-dal";
import { TProjectKeyDALFactory } from "@app/services/project-key/project-key-dal";
@@ -33,7 +42,6 @@ import { UserAliasType } from "@app/services/user-alias/user-alias-types";
import { TLicenseServiceFactory } from "../license/license-service";
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
import { TPermissionServiceFactory } from "../permission/permission-service-types";
import { TProjectUserAdditionalPrivilegeDALFactory } from "../project-user-additional-privilege/project-user-additional-privilege-dal";
import { buildScimGroup, buildScimGroupList, buildScimUser, buildScimUserList, parseScimFilter } from "./scim-fns";
import { TScimGroup, TScimServiceFactory } from "./scim-types";
@@ -55,12 +63,9 @@ type TScimServiceFactoryDep = {
| "updateMembershipById"
| "findOrgById"
>;
orgMembershipDAL: Pick<
TOrgMembershipDALFactory,
"find" | "findOne" | "create" | "updateById" | "findById" | "update"
>;
membershipUserDAL: TMembershipUserDALFactory;
projectDAL: Pick<TProjectDALFactory, "find" | "findProjectGhostUser" | "findById">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find" | "delete" | "findProjectMembershipsByUserId">;
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "findProjectMembershipsByUserId">;
groupDAL: Pick<
TGroupDALFactory,
| "create"
@@ -72,7 +77,8 @@ type TScimServiceFactoryDep = {
| "updateById"
| "update"
>;
groupProjectDAL: Pick<TGroupProjectDALFactory, "find">;
membershipGroupDAL: Pick<TMembershipGroupDALFactory, "find">;
membershipRoleDAL: Pick<TMembershipRoleDALFactory, "create" | "update">;
userGroupMembershipDAL: Pick<
TUserGroupMembershipDALFactory,
| "find"
@@ -88,7 +94,6 @@ type TScimServiceFactoryDep = {
licenseService: Pick<TLicenseServiceFactory, "getPlan" | "updateSubscriptionOrgMemberCount">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
smtpService: Pick<TSmtpService, "sendMail">;
projectUserAdditionalPrivilegeDAL: Pick<TProjectUserAdditionalPrivilegeDALFactory, "delete">;
externalGroupOrgRoleMappingDAL: TExternalGroupOrgRoleMappingDALFactory;
};
@@ -98,18 +103,18 @@ export const scimServiceFactory = ({
userDAL,
userAliasDAL,
orgDAL,
orgMembershipDAL,
projectDAL,
projectMembershipDAL,
groupDAL,
groupProjectDAL,
userGroupMembershipDAL,
projectKeyDAL,
projectBotDAL,
permissionService,
projectUserAdditionalPrivilegeDAL,
smtpService,
externalGroupOrgRoleMappingDAL
externalGroupOrgRoleMappingDAL,
membershipGroupDAL,
membershipUserDAL,
membershipRoleDAL
}: TScimServiceFactoryDep): TScimServiceFactory => {
const createScimToken: TScimServiceFactory["createScimToken"] = async ({
actor,
@@ -244,8 +249,9 @@ export const scimServiceFactory = ({
const getScimUser: TScimServiceFactory["getScimUser"] = async ({ orgMembershipId, orgId }) => {
const [membership] = await orgDAL
.findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
[`${TableName.Membership}.id` as "id"]: orgMembershipId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization
})
.catch(() => {
throw new ScimRequestError({
@@ -322,13 +328,14 @@ export const scimServiceFactory = ({
const { user: createdUser, orgMembership: createdOrgMembership } = await userDAL.transaction(async (tx) => {
let user: TUsers | undefined;
let orgMembership: TOrgMemberships;
let orgMembership: TMemberships;
if (userAlias) {
user = await userDAL.findById(userAlias.userId, tx);
orgMembership = await orgMembershipDAL.findOne(
orgMembership = await membershipUserDAL.findOne(
{
userId: user.id,
orgId
actorUserId: user.id,
scope: AccessScope.Organization,
scopeOrgId: orgId
},
tx
);
@@ -336,20 +343,24 @@ export const scimServiceFactory = ({
if (!orgMembership) {
const { role, roleId } = await getDefaultOrgMembershipRole(org.defaultMembershipRole);
orgMembership = await orgMembershipDAL.create(
orgMembership = await membershipUserDAL.create(
{
userId: userAlias.userId,
actorUserId: userAlias.userId,
inviteEmail: email.toLowerCase(),
orgId,
role,
roleId,
scopeOrgId: orgId,
scope: AccessScope.Organization,
status: user.isAccepted ? OrgMembershipStatus.Accepted : OrgMembershipStatus.Invited, // if user is fully completed, then set status to accepted, otherwise set it to invited so we can update it later
isActive: true
},
tx
);
await membershipRoleDAL.create({
membershipId: orgMembership.id,
role,
customRoleId: roleId
});
} else if (orgMembership.status === OrgMembershipStatus.Invited && user.isAccepted) {
orgMembership = await orgMembershipDAL.updateById(
orgMembership = await membershipUserDAL.updateById(
orgMembership.id,
{
status: OrgMembershipStatus.Accepted
@@ -401,8 +412,9 @@ export const scimServiceFactory = ({
const [foundOrgMembership] = await orgDAL.findMembership(
{
[`${TableName.OrgMembership}.userId` as "userId"]: user.id,
[`${TableName.OrgMembership}.orgId` as "id"]: orgId
[`${TableName.Membership}.actorUserId` as "actorUserId"]: user.id,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization
},
{ tx }
);
@@ -412,18 +424,25 @@ export const scimServiceFactory = ({
if (!orgMembership) {
const { role, roleId } = await getDefaultOrgMembershipRole(org.defaultMembershipRole);
orgMembership = await orgMembershipDAL.create(
orgMembership = await membershipUserDAL.create(
{
userId: user.id,
actorUserId: user.id,
inviteEmail: email.toLowerCase(),
orgId,
role,
roleId,
scopeOrgId: orgId,
scope: AccessScope.Organization,
status: user.isAccepted ? OrgMembershipStatus.Accepted : OrgMembershipStatus.Invited, // if user is fully completed, then set status to accepted, otherwise set it to invited so we can update it later
isActive: true
},
tx
);
await membershipRoleDAL.create(
{
membershipId: orgMembership.id,
role,
customRoleId: roleId
},
tx
);
// Only update the membership to Accepted if the user account is already completed.
} else if (orgMembership.status === OrgMembershipStatus.Invited && user.isAccepted) {
orgMembership = await orgDAL.updateMembershipById(
@@ -475,8 +494,9 @@ export const scimServiceFactory = ({
const [membership] = await orgDAL
.findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
[`${TableName.Membership}.id` as "id"]: orgMembershipId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization
})
.catch(() => {
throw new ScimRequestError({
@@ -485,7 +505,7 @@ export const scimServiceFactory = ({
});
});
if (!membership)
if (!membership || !membership.actorUserId)
throw new ScimRequestError({
detail: "User not found",
status: 404
@@ -514,7 +534,7 @@ export const scimServiceFactory = ({
org.orgAuthMethod === OrgAuthMethod.OIDC ? serverCfg.trustOidcEmails : serverCfg.trustSamlEmails;
await userDAL.transaction(async (tx) => {
await orgMembershipDAL.updateById(
await membershipUserDAL.updateById(
membership.id,
{
isActive: scimUser.active
@@ -523,7 +543,7 @@ export const scimServiceFactory = ({
);
const hasEmailChanged = scimUser.emails[0].value !== membership.email;
await userDAL.updateById(
membership.userId,
membership.actorUserId as string,
{
firstName: scimUser.name.givenName,
email: scimUser.emails[0].value.toLowerCase(),
@@ -556,8 +576,9 @@ export const scimServiceFactory = ({
const [membership] = await orgDAL
.findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
[`${TableName.Membership}.id` as "id"]: orgMembershipId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization
})
.catch(() => {
throw new ScimRequestError({
@@ -566,7 +587,7 @@ export const scimServiceFactory = ({
});
});
if (!membership)
if (!membership || !membership.actorUserId)
throw new ScimRequestError({
detail: "User not found",
status: 404
@@ -587,7 +608,7 @@ export const scimServiceFactory = ({
{
orgId,
aliasType: org.orgAuthMethod === OrgAuthMethod.OIDC ? UserAliasType.OIDC : UserAliasType.SAML,
userId: membership.userId
userId: membership.actorUserId as string
},
{
externalId
@@ -595,7 +616,7 @@ export const scimServiceFactory = ({
tx
);
await orgMembershipDAL.updateById(
await membershipUserDAL.updateById(
membership.id,
{
isActive: active
@@ -603,7 +624,7 @@ export const scimServiceFactory = ({
tx
);
await userDAL.updateById(
membership.userId,
membership.actorUserId!,
{
firstName,
email: email?.toLowerCase(),
@@ -628,8 +649,9 @@ export const scimServiceFactory = ({
const deleteScimUser: TScimServiceFactory["deleteScimUser"] = async ({ orgMembershipId, orgId }) => {
const [membership] = await orgDAL.findMembership({
[`${TableName.OrgMembership}.id` as "id"]: orgMembershipId,
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId
[`${TableName.Membership}.id` as "id"]: orgMembershipId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization
});
if (!membership)
@@ -647,13 +669,13 @@ export const scimServiceFactory = ({
await deleteOrgMembershipFn({
orgMembershipId: membership.id,
orgId: membership.orgId,
orgId: membership.scopeOrgId,
orgDAL,
projectMembershipDAL,
projectUserAdditionalPrivilegeDAL,
projectKeyDAL,
userAliasDAL,
licenseService
licenseService,
membershipUserDAL
});
return {}; // intentionally return empty object upon success
@@ -750,8 +772,9 @@ export const scimServiceFactory = ({
if (!externalGroupMapping) return;
// only get org memberships that are new (invites)
const newOrgMemberships = await orgMembershipDAL.find({
const newOrgMemberships = await membershipUserDAL.find({
status: "invited",
scope: AccessScope.Organization,
$in: {
id: members.map((member) => member.value)
}
@@ -760,7 +783,7 @@ export const scimServiceFactory = ({
if (!newOrgMemberships.length) return;
// set new membership roles to group mapping value
await orgMembershipDAL.update(
await membershipRoleDAL.update(
{
$in: {
id: newOrgMemberships.map((membership) => membership.id)
@@ -768,7 +791,7 @@ export const scimServiceFactory = ({
},
{
role: externalGroupMapping.role,
roleId: externalGroupMapping.roleId
customRoleId: externalGroupMapping.roleId
}
);
};
@@ -822,7 +845,8 @@ export const scimServiceFactory = ({
);
if (members && members.length) {
const orgMemberships = await orgMembershipDAL.find({
const orgMemberships = await membershipUserDAL.find({
scope: AccessScope.Organization,
$in: {
id: members.map((member) => member.value)
}
@@ -830,14 +854,14 @@ export const scimServiceFactory = ({
const newMembers = await addUsersToGroupByUserIds({
group,
userIds: orgMemberships.map((membership) => membership.userId as string),
userIds: orgMemberships.map((membership) => membership.actorUserId as string),
userDAL,
userGroupMembershipDAL,
orgDAL,
groupProjectDAL,
projectKeyDAL,
projectDAL,
projectBotDAL,
membershipGroupDAL,
tx
});
@@ -850,9 +874,10 @@ export const scimServiceFactory = ({
});
const orgMemberships = await orgDAL.findMembership({
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization,
$in: {
[`${TableName.OrgMembership}.userId` as "userId"]: newGroup.newMembers.map((member) => member.id)
[`${TableName.Membership}.actorUserId` as "actorUserId"]: newGroup.newMembers.map((member) => member.id)
}
});
@@ -895,9 +920,10 @@ export const scimServiceFactory = ({
.then((g) => g.members);
const orgMemberships = await orgDAL.findMembership({
[`${TableName.OrgMembership}.orgId` as "orgId"]: orgId,
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization,
$in: {
[`${TableName.OrgMembership}.userId` as "userId"]: users
[`${TableName.Membership}.actorUserId` as "actorUserId"]: users
.filter((user) => user.isPartOfGroup)
.map((user) => user.id)
}
@@ -933,10 +959,10 @@ export const scimServiceFactory = ({
}
const updatedGroup = await groupDAL.transaction(async (tx) => {
if (group.name !== displayName) {
if (group?.name !== displayName) {
await externalGroupOrgRoleMappingDAL.update(
{
groupName: group.name,
groupName: group?.name,
orgId
},
{
@@ -958,14 +984,16 @@ export const scimServiceFactory = ({
}
const orgMemberships = members.length
? await orgMembershipDAL.find({
? await membershipUserDAL.find({
[`${TableName.Membership}.scopeOrgId` as "scopeOrgId"]: orgId,
[`${TableName.Membership}.scope` as "scope"]: AccessScope.Organization,
$in: {
id: members.map((member) => member.value)
}
})
: [];
const membersIdsSet = new Set(orgMemberships.map((orgMembership) => orgMembership.userId));
const membersIdsSet = new Set(orgMemberships.map((orgMembership) => orgMembership.actorUserId as string));
const userGroupMembers = await userGroupMembershipDAL.find({
groupId: group.id
});
@@ -978,20 +1006,20 @@ export const scimServiceFactory = ({
const allMembersUserIds = directMemberUserIds.concat(pendingGroupAdditionsUserIds);
const allMembersUserIdsSet = new Set(allMembersUserIds);
const toAddUserIds = orgMemberships.filter((member) => !allMembersUserIdsSet.has(member.userId as string));
const toAddUserIds = orgMemberships.filter((member) => !allMembersUserIdsSet.has(member.actorUserId as string));
const toRemoveUserIds = allMembersUserIds.filter((userId) => !membersIdsSet.has(userId));
if (toAddUserIds.length) {
await addUsersToGroupByUserIds({
group,
userIds: toAddUserIds.map((member) => member.userId as string),
userIds: toAddUserIds.map((member) => member.actorUserId as string),
userDAL,
userGroupMembershipDAL,
orgDAL,
groupProjectDAL,
projectKeyDAL,
projectDAL,
projectBotDAL,
membershipGroupDAL,
tx
});
}
@@ -1002,7 +1030,7 @@ export const scimServiceFactory = ({
userIds: toRemoveUserIds,
userDAL,
userGroupMembershipDAL,
groupProjectDAL,
membershipGroupDAL,
projectKeyDAL,
tx
});