mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-25 14:05:03 +00:00
feat(server): removed name and description and fixed api for user privileges
This commit is contained in:
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
|
@ -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 };
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
};
|
||||
|
@ -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 };
|
||||
|
@ -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: {
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
]
|
||||
});
|
||||
|
Reference in New Issue
Block a user