feat(server): removed name and description and fixed api for user privileges

This commit is contained in:
Akhil Mohan
2024-03-28 15:29:54 +05:30
parent f551a4158d
commit 6b51c7269a
12 changed files with 148 additions and 157 deletions

View File

@ -9,9 +9,7 @@ import { TImmutableDBKeys } from "./models";
export const IdentityProjectAdditionalPrivilegeSchema = z.object({
id: z.string().uuid(),
name: z.string(),
slug: z.string(),
description: z.string().nullable().optional(),
projectMembershipId: z.string().uuid(),
isTemporary: z.boolean().default(false),
temporaryMode: z.string().nullable().optional(),

View File

@ -9,9 +9,7 @@ import { TImmutableDBKeys } from "./models";
export const ProjectUserAdditionalPrivilegeSchema = z.object({
id: z.string().uuid(),
name: z.string(),
slug: z.string(),
description: z.string().nullable().optional(),
projectMembershipId: z.string().uuid(),
isTemporary: z.boolean().default(false),
temporaryMode: z.string().nullable().optional(),

View File

@ -31,8 +31,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
message: "Slug must be a valid slug"
})
),
name: z.string().trim().min(1),
description: z.string().trim().optional(),
permissions: z.any().array(),
isPackedPermission: z.boolean().optional().default(true),
isTemporary: z.literal(false).default(false)
@ -48,8 +46,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
}),
name: z.string().trim(),
description: z.string().trim().optional(),
permissions: z.any().array(),
isTemporary: z.literal(true),
isPackedPermission: z.boolean().optional().default(true),
@ -70,6 +66,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
...req.body,
permissions: JSON.stringify(
req.body.isPackedPermission ? req.body.permissions : packRules(req.body.permissions)
@ -96,8 +93,6 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
}),
name: z.string().trim(),
description: z.string().trim().optional(),
permissions: z.any().array(),
isPackedPermission: z.boolean().optional().default(true),
isTemporary: z.boolean(),
@ -118,6 +113,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
...req.body,
permissions: req.body.permissions
? JSON.stringify(req.body.isPackedPermission ? req.body.permissions : packRules(req.body.permissions))
@ -146,6 +142,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
const privilege = await server.services.identityProjectAdditionalPrivilege.deleteById({
actorId: req.permission.id,
actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
privilegeId: req.params.privilegeId
});
@ -170,6 +167,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
handler: async (req) => {
const privilege = await server.services.identityProjectAdditionalPrivilege.getPrivilegeDetailsById({
actorId: req.permission.id,
actorAuthMethod: req.permission.authMethod,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
privilegeId: req.params.privilegeId
@ -197,6 +195,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
const privileges = await server.services.identityProjectAdditionalPrivilege.listIdentityProjectPrivileges({
actorId: req.permission.id,
actor: req.permission.type,
actorAuthMethod: req.permission.authMethod,
actorOrgId: req.permission.orgId,
projectId: req.body.projectId,
identityId: req.body.identityId

View File

@ -5,7 +5,6 @@ import { z } from "zod";
import { ProjectUserAdditionalPrivilegeSchema } from "@app/db/schemas";
import { ProjectUserAdditionalPrivilegeTemporaryMode } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-types";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { zpStr } from "@app/lib/zod";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@ -17,36 +16,29 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
body: z.union([
z.object({
projectMembershipId: z.string(),
// to disallow empty string
slug: zpStr(
z
.string()
.max(60)
.trim()
.optional()
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
})
),
name: z.string().trim(),
description: z.string().trim().optional(),
slug: z
.string()
.min(1)
.max(60)
.trim()
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
}),
permissions: z.any().array(),
isTemporary: z.literal(false).default(false)
}),
z.object({
projectMembershipId: z.string(),
slug: zpStr(
z
.string()
.max(60)
.trim()
.optional()
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
})
),
slug: z
.string()
.min(1)
.max(60)
.trim()
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
}),
name: z.string().trim(),
description: z.string().trim().optional(),
permissions: z.any().array(),
@ -68,6 +60,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
...req.body,
permissions: JSON.stringify(req.body.permissions)
});
@ -88,11 +81,10 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
.string()
.max(60)
.trim()
.refine((v) => v.toLowerCase() === v, "Slug must be lowercase")
.refine((v) => slugify(v) === v, {
message: "Slug must be a valid slug"
}),
name: z.string().trim(),
description: z.string().trim().optional(),
permissions: z.any().array(),
isTemporary: z.boolean(),
temporaryMode: z.nativeEnum(ProjectUserAdditionalPrivilegeTemporaryMode),
@ -112,6 +104,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
...req.body,
permissions: req.body.permissions ? JSON.stringify(req.body.permissions) : undefined,
privilegeId: req.params.privilegeId
@ -139,12 +132,39 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
privilegeId: req.params.privilegeId
});
return { privilege };
}
});
server.route({
url: "/",
method: "GET",
schema: {
querystring: z.object({
projectMembershipId: z.string()
}),
response: {
200: z.object({
privileges: ProjectUserAdditionalPrivilegeSchema.array()
})
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const privileges = await server.services.projectUserAdditionalPrivilege.listPrivileges({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
projectMembershipId: req.query.projectMembershipId
});
return { privileges };
}
});
server.route({
url: "/:privilegeId",
method: "GET",
@ -164,6 +184,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
actorAuthMethod: req.permission.authMethod,
privilegeId: req.params.privilegeId
});
return { privilege };

View File

@ -34,7 +34,6 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
permissionService
}: TIdentityProjectAdditionalPrivilegeServiceFactoryDep) => {
const create = async ({
name,
slug,
actor,
actorId,
@ -42,7 +41,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
identityId,
permissions: customPermission,
actorOrgId,
description,
actorAuthMethod,
...dto
}: TCreateIdentityPrivilegeDTO) => {
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
@ -53,6 +52,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
@ -60,6 +60,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
ActorType.IDENTITY,
identityId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@ -76,9 +77,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
const additionalPrivilege = await identityProjectAdditionalPrivilegeDAL.create({
projectMembershipId: identityProjectMembership.id,
slug,
permissions: customPermission,
name,
description
permissions: customPermission
});
return additionalPrivilege;
}
@ -88,8 +87,6 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
projectMembershipId: identityProjectMembership.id,
slug,
permissions: customPermission,
name,
description,
isTemporary: true,
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative,
temporaryRange: dto.temporaryRange,
@ -99,7 +96,14 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
return additionalPrivilege;
};
const updateById = async ({ privilegeId, actorOrgId, actor, actorId, ...dto }: TUpdateIdentityPrivilegeDTO) => {
const updateById = async ({
privilegeId,
actorOrgId,
actor,
actorId,
actorAuthMethod,
...dto
}: TUpdateIdentityPrivilegeDTO) => {
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(privilegeId);
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
@ -110,6 +114,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
@ -117,6 +122,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
ActorType.IDENTITY,
identityProjectMembership.identityId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@ -155,7 +161,13 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
return additionalPrivilege;
};
const deleteById = async ({ actorId, actor, actorOrgId, privilegeId }: TDeleteIdentityPrivilegeDTO) => {
const deleteById = async ({
actorId,
actor,
actorOrgId,
privilegeId,
actorAuthMethod
}: TDeleteIdentityPrivilegeDTO) => {
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(privilegeId);
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
@ -166,6 +178,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
@ -173,6 +186,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
ActorType.IDENTITY,
identityProjectMembership.identityId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@ -187,7 +201,8 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
privilegeId,
actorOrgId,
actor,
actorId
actorId,
actorAuthMethod
}: TGetIdentityPrivilegeDetailsDTO) => {
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(privilegeId);
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
@ -199,6 +214,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
@ -206,6 +222,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
ActorType.IDENTITY,
identityProjectMembership.identityId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
@ -220,7 +237,8 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
identityId,
actorOrgId,
actor,
actorId
actorId,
actorAuthMethod
}: TListIdentityPrivilegesDTO) => {
const identityProjectMembership = await identityProjectDAL.findOne({ projectId, identityId });
if (!identityProjectMembership) throw new BadRequestError({ message: `Failed to find identity` });
@ -229,6 +247,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
@ -236,6 +255,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
ActorType.IDENTITY,
identityProjectMembership.identityId,
identityProjectMembership.projectId,
actorAuthMethod,
actorOrgId
);
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);

View File

@ -9,18 +9,14 @@ export type TCreateIdentityPrivilegeDTO = (
permissions: unknown;
identityId: string;
projectId: string;
name: string;
slug: string;
description?: string;
isTemporary: false;
}
| {
permissions: unknown;
identityId: string;
projectId: string;
name: string;
slug: string;
description?: string;
isTemporary: true;
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative;
temporaryRange: string;
@ -32,9 +28,7 @@ export type TCreateIdentityPrivilegeDTO = (
export type TUpdateIdentityPrivilegeDTO = { privilegeId: string } & Omit<TProjectPermission, "projectId"> &
Partial<{
permissions: unknown;
name: string;
slug: string;
description?: string;
isTemporary: boolean;
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative;
temporaryRange: string;

View File

@ -180,10 +180,12 @@ export const permissionServiceFactory = ({
authMethod: ActorAuthMethod,
userOrgId?: string
): Promise<TProjectPermissionRT<ActorType.USER>> => {
const membership = await permissionDAL.getProjectPermission(userId, projectId);
if (!membership) throw new UnauthorizedError({ name: "User not in project" });
const userProjectPermission = await permissionDAL.getProjectPermission(userId, projectId);
if (!userProjectPermission) throw new UnauthorizedError({ name: "User not in project" });
if (membership.roles.some(({ role, permissions }) => role === ProjectMembershipRole.Custom && !permissions)) {
if (
userProjectPermission.roles.some(({ role, permissions }) => role === ProjectMembershipRole.Custom && !permissions)
) {
throw new BadRequestError({ name: "Custom permission not found" });
}
@ -192,11 +194,11 @@ export const permissionServiceFactory = ({
// Extra: This means that when users are using API keys to make requests, they can't use slug-based routes.
// Slug-based routes depend on the organization ID being present on the request, since project slugs aren't globally unique, and we need a way to filter by organization.
if (userOrgId !== "API_KEY" && membership.orgId !== userOrgId) {
if (userOrgId !== "API_KEY" && userProjectPermission.orgId !== userOrgId) {
throw new UnauthorizedError({ name: "You are not logged into this organization" });
}
validateOrgSAML(authMethod, membership.orgAuthEnforced);
validateOrgSAML(authMethod, userProjectPermission.orgAuthEnforced);
// join two permissions and pass to build the final permission set
const rolePermissions = userProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
@ -210,7 +212,9 @@ export const permissionServiceFactory = ({
permission: buildProjectPermission(rolePermissions.concat(additionalPrivileges)),
membership: userProjectPermission,
hasRole: (role: string) =>
membership.roles.findIndex(({ role: slug, customRoleSlug }) => role === slug || slug === customRoleSlug) !== -1
userProjectPermission.roles.findIndex(
({ role: slug, customRoleSlug }) => role === slug || slug === customRoleSlug
) !== -1
};
};

View File

@ -12,6 +12,7 @@ import {
TCreateUserPrivilegeDTO,
TDeleteUserPrivilegeDTO,
TGetUserPrivilegeDetailsDTO,
TListUserPrivilegesDTO,
TUpdateUserPrivilegeDTO
} from "./project-user-additional-privilege-types";
@ -31,13 +32,12 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
permissionService
}: TProjectUserAdditionalPrivilegeServiceFactoryDep) => {
const create = async ({
name,
slug,
actor,
actorId,
permissions: customPermission,
actorOrgId,
description,
actorAuthMethod,
projectMembershipId,
...dto
}: TCreateUserPrivilegeDTO) => {
@ -48,6 +48,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
projectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
@ -59,9 +60,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
const additionalPrivilege = await projectUserAdditionalPrivilegeDAL.create({
projectMembershipId,
slug,
permissions: customPermission,
name,
description
permissions: customPermission
});
return additionalPrivilege;
}
@ -71,8 +70,6 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
projectMembershipId,
slug,
permissions: customPermission,
name,
description,
isTemporary: true,
temporaryMode: ProjectUserAdditionalPrivilegeTemporaryMode.Relative,
temporaryRange: dto.temporaryRange,
@ -82,7 +79,14 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
return additionalPrivilege;
};
const updateById = async ({ privilegeId, actorOrgId, actor, actorId, ...dto }: TUpdateUserPrivilegeDTO) => {
const updateById = async ({
privilegeId,
actorOrgId,
actor,
actorId,
actorAuthMethod,
...dto
}: TUpdateUserPrivilegeDTO) => {
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
if (!userPrivilege) throw new BadRequestError({ message: "User additional privilege not found" });
@ -93,6 +97,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
projectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
@ -129,7 +134,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
return additionalPrivilege;
};
const deleteById = async ({ actorId, actor, actorOrgId, privilegeId }: TDeleteUserPrivilegeDTO) => {
const deleteById = async ({ actorId, actor, actorOrgId, actorAuthMethod, privilegeId }: TDeleteUserPrivilegeDTO) => {
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
if (!userPrivilege) throw new BadRequestError({ message: "User additional privilege not found" });
@ -140,6 +145,7 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
projectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
@ -148,7 +154,13 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
return deletedPrivilege;
};
const getPrivilegeDetailsById = async ({ privilegeId, actorOrgId, actor, actorId }: TGetUserPrivilegeDetailsDTO) => {
const getPrivilegeDetailsById = async ({
privilegeId,
actorOrgId,
actor,
actorId,
actorAuthMethod
}: TGetUserPrivilegeDetailsDTO) => {
const userPrivilege = await projectUserAdditionalPrivilegeDAL.findById(privilegeId);
if (!userPrivilege) throw new BadRequestError({ message: "User additional privilege not found" });
@ -159,17 +171,42 @@ export const projectUserAdditionalPrivilegeServiceFactory = ({
actor,
actorId,
projectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
return userPrivilege;
};
const listPrivileges = async ({
projectMembershipId,
actorOrgId,
actor,
actorId,
actorAuthMethod
}: TListUserPrivilegesDTO) => {
const projectMembership = await projectMembershipDAL.findById(projectMembershipId);
if (!projectMembership) throw new BadRequestError({ message: "Project membership not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectMembership.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
const userPrivileges = await projectUserAdditionalPrivilegeDAL.find({ projectMembershipId });
return userPrivileges;
};
return {
create,
updateById,
deleteById,
getPrivilegeDetailsById
getPrivilegeDetailsById,
listPrivileges
};
};

View File

@ -8,17 +8,13 @@ export type TCreateUserPrivilegeDTO = (
| {
permissions: unknown;
projectMembershipId: string;
name: string;
slug: string;
description?: string;
isTemporary: false;
}
| {
permissions: unknown;
projectMembershipId: string;
name: string;
slug: string;
description?: string;
isTemporary: true;
temporaryMode: ProjectUserAdditionalPrivilegeTemporaryMode.Relative;
temporaryRange: string;
@ -30,9 +26,7 @@ export type TCreateUserPrivilegeDTO = (
export type TUpdateUserPrivilegeDTO = { privilegeId: string } & Omit<TProjectPermission, "projectId"> &
Partial<{
permissions: unknown;
name: string;
slug: string;
description?: string;
isTemporary: boolean;
temporaryMode: ProjectUserAdditionalPrivilegeTemporaryMode.Relative;
temporaryRange: string;
@ -42,3 +36,5 @@ export type TUpdateUserPrivilegeDTO = { privilegeId: string } & Omit<TProjectPer
export type TDeleteUserPrivilegeDTO = Omit<TProjectPermission, "projectId"> & { privilegeId: string };
export type TGetUserPrivilegeDetailsDTO = Omit<TProjectPermission, "projectId"> & { privilegeId: string };
export type TListUserPrivilegesDTO = Omit<TProjectPermission, "projectId"> & { projectMembershipId: string };

View File

@ -40,20 +40,6 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
lastName: true,
id: true
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
additionalPrivileges: z.array(
z.object({
id: z.string(),
name: z.string(),
slug: z.string(),
description: z.string().optional().nullable(),
isTemporary: z.boolean(),
temporaryMode: z.string().optional().nullable(),
temporaryRange: z.string().nullable().optional(),
temporaryAccessStartTime: z.date().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional(),
createdAt: z.date()
})
),
roles: z.array(
z.object({
id: z.string(),
@ -172,7 +158,7 @@ export const registerProjectMembershipRouter = async (server: FastifyZodProvider
])
)
.min(1)
.refine((data) => data.some(({ isTemporary }) => !isTemporary), "At least long lived role is required")
.refine((data) => data.some(({ isTemporary }) => !isTemporary), "At least one long lived role is required")
.describe(PROJECTS.UPDATE_USER_MEMBERSHIP.roles)
}),
response: {

View File

@ -73,20 +73,6 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
lastName: true,
id: true
}).merge(UserEncryptionKeysSchema.pick({ publicKey: true })),
additionalPrivileges: z.array(
z.object({
id: z.string(),
name: z.string(),
slug: z.string(),
description: z.string().optional().nullable(),
isTemporary: z.boolean(),
temporaryMode: z.string().optional().nullable(),
temporaryRange: z.string().nullable().optional(),
temporaryAccessStartTime: z.date().nullable().optional(),
temporaryAccessEndTime: z.date().nullable().optional(),
createdAt: z.date()
})
),
roles: z.array(
z.object({
id: z.string(),

View File

@ -29,11 +29,6 @@ export const projectMembershipDALFactory = (db: TDbClient) => {
`${TableName.ProjectUserMembershipRole}.customRoleId`,
`${TableName.ProjectRoles}.id`
)
.leftJoin(
TableName.ProjectUserAdditionalPrivilege,
`${TableName.ProjectMembership}.id`,
`${TableName.ProjectUserAdditionalPrivilege}.projectMembershipId`
)
.select(
db.ref("id").withSchema(TableName.ProjectMembership),
db.ref("isGhost").withSchema(TableName.Users),
@ -52,23 +47,7 @@ export const projectMembershipDALFactory = (db: TDbClient) => {
db.ref("isTemporary").withSchema(TableName.ProjectUserMembershipRole),
db.ref("temporaryRange").withSchema(TableName.ProjectUserMembershipRole),
db.ref("temporaryAccessStartTime").withSchema(TableName.ProjectUserMembershipRole),
db.ref("temporaryAccessEndTime").withSchema(TableName.ProjectUserMembershipRole),
db.ref("id").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApId"),
db.ref("name").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApName"),
db.ref("description").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApDescription"),
db.ref("slug").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApSlug"),
db.ref("temporaryMode").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApTemporaryMode"),
db.ref("isTemporary").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApIsTemporary"),
db.ref("createdAt").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApCreatedAt"),
db.ref("temporaryRange").withSchema(TableName.ProjectUserAdditionalPrivilege).as("userApTemporaryRange"),
db
.ref("temporaryAccessStartTime")
.withSchema(TableName.ProjectUserAdditionalPrivilege)
.as("userApTemporaryAccessStartTime"),
db
.ref("temporaryAccessEndTime")
.withSchema(TableName.ProjectUserAdditionalPrivilege)
.as("userApTemporaryAccessEndTime")
db.ref("temporaryAccessEndTime").withSchema(TableName.ProjectUserMembershipRole)
)
.where({ isGhost: false });
@ -108,33 +87,6 @@ export const projectMembershipDALFactory = (db: TDbClient) => {
temporaryAccessStartTime,
isTemporary
})
},
{
label: "additionalPrivileges" as const,
key: "userApId",
mapper: ({
userApId,
userApDescription,
userApName,
userApSlug,
userApIsTemporary,
userApTemporaryMode,
userApTemporaryRange,
userApTemporaryAccessEndTime,
userApTemporaryAccessStartTime,
userApCreatedAt
}) => ({
id: userApId,
name: userApName,
description: userApDescription,
slug: userApSlug,
temporaryRange: userApTemporaryRange,
temporaryMode: userApTemporaryMode,
temporaryAccessEndTime: userApTemporaryAccessEndTime,
temporaryAccessStartTime: userApTemporaryAccessStartTime,
isTemporary: userApIsTemporary,
createdAt: userApCreatedAt
})
}
]
});