mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 23:26:20 +00:00
feat(server): added identity privilege route changes with project slug
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
import { packRules } from "@casl/ability/extra";
|
import { MongoAbility, RawRuleOf } from "@casl/ability";
|
||||||
|
import { PackRule, packRules, unpackRules } from "@casl/ability/extra";
|
||||||
import slugify from "@sindresorhus/slugify";
|
import slugify from "@sindresorhus/slugify";
|
||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { IdentityProjectAdditionalPrivilegeSchema } from "@app/db/schemas";
|
import { IdentityProjectAdditionalPrivilegeSchema } from "@app/db/schemas";
|
||||||
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
|
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
|
||||||
|
import { ProjectPermissionSet } from "@app/ee/services/permission/project-permission";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { zpStr } from "@app/lib/zod";
|
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@@ -18,37 +19,37 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
body: z.union([
|
body: z.union([
|
||||||
z.object({
|
z.object({
|
||||||
identityId: z.string().min(1),
|
identityId: z.string().min(1),
|
||||||
projectId: z.string().min(1),
|
projectSlug: z.string().min(1),
|
||||||
// disallow empty string
|
slug: z
|
||||||
slug: zpStr(
|
.string()
|
||||||
z
|
.min(1)
|
||||||
.string()
|
.max(60)
|
||||||
.max(60)
|
.trim()
|
||||||
.trim()
|
.optional()
|
||||||
.optional()
|
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
|
||||||
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
|
.refine((v) => slugify(v) === v, {
|
||||||
.refine((v) => slugify(v) === v, {
|
message: "Slug must be a valid slug"
|
||||||
message: "Slug must be a valid slug"
|
}),
|
||||||
})
|
|
||||||
),
|
|
||||||
permissions: z.any().array(),
|
permissions: z.any().array(),
|
||||||
isPackedPermission: z.boolean().optional().default(true),
|
isPackedPermission: z.boolean().optional().default(false),
|
||||||
isTemporary: z.literal(false).default(false)
|
isTemporary: z.literal(false).default(false)
|
||||||
}),
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
identityId: z.string(),
|
identityId: z.string(),
|
||||||
projectId: z.string(),
|
projectSlug: z.string().min(1),
|
||||||
slug: z
|
slug: z
|
||||||
.string()
|
.string()
|
||||||
|
.min(1)
|
||||||
.max(60)
|
.max(60)
|
||||||
.trim()
|
.trim()
|
||||||
|
.optional()
|
||||||
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
|
.default(`privilege-${slugify(alphaNumericNanoId(12))}`)
|
||||||
.refine((v) => slugify(v) === v, {
|
.refine((v) => slugify(v) === v, {
|
||||||
message: "Slug must be a valid slug"
|
message: "Slug must be a valid slug"
|
||||||
}),
|
}),
|
||||||
permissions: z.any().array(),
|
permissions: z.any().array(),
|
||||||
isTemporary: z.literal(true),
|
isTemporary: z.literal(true),
|
||||||
isPackedPermission: z.boolean().optional().default(true),
|
isPackedPermission: z.boolean().optional().default(false),
|
||||||
temporaryMode: z.nativeEnum(IdentityProjectAdditionalPrivilegeTemporaryMode),
|
temporaryMode: z.nativeEnum(IdentityProjectAdditionalPrivilegeTemporaryMode),
|
||||||
temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be a positive number"),
|
temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be a positive number"),
|
||||||
temporaryAccessStartTime: z.string().datetime()
|
temporaryAccessStartTime: z.string().datetime()
|
||||||
@@ -77,30 +78,33 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:privilegeId",
|
url: "/",
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
body: z.object({
|
||||||
privilegeId: z.string()
|
// disallow empty string
|
||||||
|
slug: z.string().min(1),
|
||||||
|
identityId: z.string().min(1),
|
||||||
|
projectSlug: z.string().min(1),
|
||||||
|
data: z
|
||||||
|
.object({
|
||||||
|
slug: z
|
||||||
|
.string()
|
||||||
|
.min(1)
|
||||||
|
.max(60)
|
||||||
|
.trim()
|
||||||
|
.refine((v) => slugify(v) === v, {
|
||||||
|
message: "Slug must be a valid slug"
|
||||||
|
}),
|
||||||
|
isPackedPermission: z.boolean().optional().default(false),
|
||||||
|
permissions: z.any().array(),
|
||||||
|
isTemporary: z.boolean(),
|
||||||
|
temporaryMode: z.nativeEnum(IdentityProjectAdditionalPrivilegeTemporaryMode),
|
||||||
|
temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be a positive number"),
|
||||||
|
temporaryAccessStartTime: z.string().datetime()
|
||||||
|
})
|
||||||
|
.partial()
|
||||||
}),
|
}),
|
||||||
body: z
|
|
||||||
.object({
|
|
||||||
// disallow empty string
|
|
||||||
slug: z
|
|
||||||
.string()
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
}),
|
|
||||||
permissions: z.any().array(),
|
|
||||||
isPackedPermission: z.boolean().optional().default(true),
|
|
||||||
isTemporary: z.boolean(),
|
|
||||||
temporaryMode: z.nativeEnum(IdentityProjectAdditionalPrivilegeTemporaryMode),
|
|
||||||
temporaryRange: z.string().refine((val) => ms(val) > 0, "Temporary range must be a positive number"),
|
|
||||||
temporaryAccessStartTime: z.string().datetime()
|
|
||||||
})
|
|
||||||
.partial(),
|
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
privilege: IdentityProjectAdditionalPrivilegeSchema
|
privilege: IdentityProjectAdditionalPrivilegeSchema
|
||||||
@@ -109,27 +113,32 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const privilege = await server.services.identityProjectAdditionalPrivilege.updateById({
|
const { isPackedPermission, ...data } = req.body.data;
|
||||||
|
const privilege = await server.services.identityProjectAdditionalPrivilege.updateBySlug({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
...req.body,
|
...req.body,
|
||||||
permissions: req.body.permissions
|
data: {
|
||||||
? JSON.stringify(req.body.isPackedPermission ? req.body.permissions : packRules(req.body.permissions))
|
...data,
|
||||||
: undefined,
|
permissions: data?.permissions
|
||||||
privilegeId: req.params.privilegeId
|
? JSON.stringify(isPackedPermission ? data?.permissions : packRules(data.permissions))
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return { privilege };
|
return { privilege };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:privilegeId",
|
url: "/",
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
body: z.object({
|
||||||
privilegeId: z.string()
|
slug: z.string().min(1),
|
||||||
|
identityId: z.string().min(1),
|
||||||
|
projectSlug: z.string().min(1)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -139,23 +148,27 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const privilege = await server.services.identityProjectAdditionalPrivilege.deleteById({
|
const privilege = await server.services.identityProjectAdditionalPrivilege.deleteBySlug({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
privilegeId: req.params.privilegeId
|
...req.body
|
||||||
});
|
});
|
||||||
return { privilege };
|
return { privilege };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/:privilegeId",
|
url: "/:slug",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
privilegeId: z.string()
|
slug: z.string()
|
||||||
|
}),
|
||||||
|
querystring: z.object({
|
||||||
|
identityId: z.string().min(1),
|
||||||
|
projectSlug: z.string().min(1)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -165,24 +178,29 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const privilege = await server.services.identityProjectAdditionalPrivilege.getPrivilegeDetailsById({
|
const privilege = await server.services.identityProjectAdditionalPrivilege.getPrivilegeDetailsBySlug({
|
||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
privilegeId: req.params.privilegeId
|
slug: req.params.slug,
|
||||||
|
...req.query
|
||||||
});
|
});
|
||||||
return { privilege };
|
return { privilege };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
url: "/permissions",
|
url: "/",
|
||||||
method: "POST",
|
method: "GET",
|
||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
querystring: z.object({
|
||||||
identityId: z.string(),
|
identityId: z.string().min(1),
|
||||||
projectId: z.string()
|
projectSlug: z.string().min(1),
|
||||||
|
unpacked: z
|
||||||
|
.enum(["false", "true"])
|
||||||
|
.transform((el) => el === "true")
|
||||||
|
.default("true")
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -197,9 +215,16 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
projectId: req.body.projectId,
|
...req.query
|
||||||
identityId: req.body.identityId
|
|
||||||
});
|
});
|
||||||
|
if (req.query.unpacked) {
|
||||||
|
return {
|
||||||
|
privileges: privileges.map(({ permissions, ...el }) => ({
|
||||||
|
...el,
|
||||||
|
permissions: unpackRules(permissions as PackRule<RawRuleOf<MongoAbility<ProjectPermissionSet>>>[])
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
}
|
||||||
return { privileges };
|
return { privileges };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+79
-61
@@ -5,6 +5,7 @@ import { isAtLeastAsPrivileged } from "@app/lib/casl";
|
|||||||
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
|
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
import { TIdentityProjectDALFactory } from "@app/services/identity-project/identity-project-dal";
|
||||||
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
|
||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "../permission/project-permission";
|
||||||
@@ -21,6 +22,7 @@ import {
|
|||||||
type TIdentityProjectAdditionalPrivilegeServiceFactoryDep = {
|
type TIdentityProjectAdditionalPrivilegeServiceFactoryDep = {
|
||||||
identityProjectAdditionalPrivilegeDAL: TIdentityProjectAdditionalPrivilegeDALFactory;
|
identityProjectAdditionalPrivilegeDAL: TIdentityProjectAdditionalPrivilegeDALFactory;
|
||||||
identityProjectDAL: Pick<TIdentityProjectDALFactory, "findOne" | "findById">;
|
identityProjectDAL: Pick<TIdentityProjectDALFactory, "findOne" | "findById">;
|
||||||
|
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,19 +33,24 @@ export type TIdentityProjectAdditionalPrivilegeServiceFactory = ReturnType<
|
|||||||
export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
||||||
identityProjectAdditionalPrivilegeDAL,
|
identityProjectAdditionalPrivilegeDAL,
|
||||||
identityProjectDAL,
|
identityProjectDAL,
|
||||||
permissionService
|
permissionService,
|
||||||
|
projectDAL
|
||||||
}: TIdentityProjectAdditionalPrivilegeServiceFactoryDep) => {
|
}: TIdentityProjectAdditionalPrivilegeServiceFactoryDep) => {
|
||||||
const create = async ({
|
const create = async ({
|
||||||
slug,
|
slug,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
projectId,
|
|
||||||
identityId,
|
identityId,
|
||||||
|
projectSlug,
|
||||||
permissions: customPermission,
|
permissions: customPermission,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
...dto
|
...dto
|
||||||
}: TCreateIdentityPrivilegeDTO) => {
|
}: TCreateIdentityPrivilegeDTO) => {
|
||||||
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
const projectId = project.id;
|
||||||
|
|
||||||
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||||
if (!identityProjectMembership)
|
if (!identityProjectMembership)
|
||||||
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||||
@@ -65,7 +72,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
);
|
);
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
||||||
if (!hasRequiredPriviledges)
|
if (!hasRequiredPriviledges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
slug,
|
slug,
|
||||||
@@ -96,19 +103,23 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
return additionalPrivilege;
|
return additionalPrivilege;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateById = async ({
|
const updateBySlug = async ({
|
||||||
privilegeId,
|
projectSlug,
|
||||||
|
slug,
|
||||||
|
identityId,
|
||||||
|
data,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
actorAuthMethod,
|
actorAuthMethod
|
||||||
...dto
|
|
||||||
}: TUpdateIdentityPrivilegeDTO) => {
|
}: TUpdateIdentityPrivilegeDTO) => {
|
||||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(privilegeId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
const projectId = project.id;
|
||||||
|
|
||||||
const identityProjectMembership = await identityProjectDAL.findById(identityPrivilege.projectMembershipId);
|
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||||
if (!identityProjectMembership) throw new BadRequestError({ message: `Failed to find identity` });
|
if (!identityProjectMembership)
|
||||||
|
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
@@ -127,23 +138,28 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
);
|
);
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
||||||
if (!hasRequiredPriviledges)
|
if (!hasRequiredPriviledges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to update more privileged identity" });
|
||||||
|
|
||||||
if (dto?.slug) {
|
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
|
slug,
|
||||||
|
projectMembershipId: identityProjectMembership.id
|
||||||
|
});
|
||||||
|
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
||||||
|
if (data?.slug) {
|
||||||
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
const existingSlug = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
slug: dto.slug,
|
slug: data.slug,
|
||||||
projectMembershipId: identityProjectMembership.id
|
projectMembershipId: identityProjectMembership.id
|
||||||
});
|
});
|
||||||
if (existingSlug && existingSlug.id !== identityPrivilege.id)
|
if (existingSlug && existingSlug.id !== identityPrivilege.id)
|
||||||
throw new BadRequestError({ message: "Additional privilege of provided slug exist" });
|
throw new BadRequestError({ message: "Additional privilege of provided slug exist" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const isTemporary = typeof dto?.isTemporary !== "undefined" ? dto.isTemporary : identityPrivilege.isTemporary;
|
const isTemporary = typeof data?.isTemporary !== "undefined" ? data.isTemporary : identityPrivilege.isTemporary;
|
||||||
if (isTemporary) {
|
if (isTemporary) {
|
||||||
const temporaryAccessStartTime = dto?.temporaryAccessStartTime || identityPrivilege?.temporaryAccessStartTime;
|
const temporaryAccessStartTime = data?.temporaryAccessStartTime || identityPrivilege?.temporaryAccessStartTime;
|
||||||
const temporaryRange = dto?.temporaryRange || identityPrivilege?.temporaryRange;
|
const temporaryRange = data?.temporaryRange || identityPrivilege?.temporaryRange;
|
||||||
const additionalPrivilege = await identityProjectAdditionalPrivilegeDAL.updateById(identityPrivilege.id, {
|
const additionalPrivilege = await identityProjectAdditionalPrivilegeDAL.updateById(identityPrivilege.id, {
|
||||||
...dto,
|
...data,
|
||||||
temporaryAccessStartTime: new Date(temporaryAccessStartTime || ""),
|
temporaryAccessStartTime: new Date(temporaryAccessStartTime || ""),
|
||||||
temporaryAccessEndTime: new Date(new Date(temporaryAccessStartTime || "").getTime() + ms(temporaryRange || ""))
|
temporaryAccessEndTime: new Date(new Date(temporaryAccessStartTime || "").getTime() + ms(temporaryRange || ""))
|
||||||
});
|
});
|
||||||
@@ -151,7 +167,7 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const additionalPrivilege = await identityProjectAdditionalPrivilegeDAL.updateById(identityPrivilege.id, {
|
const additionalPrivilege = await identityProjectAdditionalPrivilegeDAL.updateById(identityPrivilege.id, {
|
||||||
...dto,
|
...data,
|
||||||
isTemporary: false,
|
isTemporary: false,
|
||||||
temporaryAccessStartTime: null,
|
temporaryAccessStartTime: null,
|
||||||
temporaryAccessEndTime: null,
|
temporaryAccessEndTime: null,
|
||||||
@@ -161,18 +177,22 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
return additionalPrivilege;
|
return additionalPrivilege;
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteById = async ({
|
const deleteBySlug = async ({
|
||||||
actorId,
|
actorId,
|
||||||
|
slug,
|
||||||
|
identityId,
|
||||||
|
projectSlug,
|
||||||
actor,
|
actor,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
privilegeId,
|
|
||||||
actorAuthMethod
|
actorAuthMethod
|
||||||
}: TDeleteIdentityPrivilegeDTO) => {
|
}: TDeleteIdentityPrivilegeDTO) => {
|
||||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(privilegeId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
const projectId = project.id;
|
||||||
|
|
||||||
const identityProjectMembership = await identityProjectDAL.findById(identityPrivilege.projectMembershipId);
|
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||||
if (!identityProjectMembership) throw new BadRequestError({ message: `Failed to find identity` });
|
if (!identityProjectMembership)
|
||||||
|
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||||
|
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
@@ -191,25 +211,34 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
);
|
);
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
||||||
if (!hasRequiredPriviledges)
|
if (!hasRequiredPriviledges)
|
||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
throw new ForbiddenRequestError({ message: "Failed to edit more privileged identity" });
|
||||||
|
|
||||||
|
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
|
slug,
|
||||||
|
projectMembershipId: identityProjectMembership.id
|
||||||
|
});
|
||||||
|
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
||||||
|
|
||||||
const deletedPrivilege = await identityProjectAdditionalPrivilegeDAL.deleteById(identityPrivilege.id);
|
const deletedPrivilege = await identityProjectAdditionalPrivilegeDAL.deleteById(identityPrivilege.id);
|
||||||
return deletedPrivilege;
|
return deletedPrivilege;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPrivilegeDetailsById = async ({
|
const getPrivilegeDetailsBySlug = async ({
|
||||||
privilegeId,
|
projectSlug,
|
||||||
|
identityId,
|
||||||
|
slug,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
actorAuthMethod
|
actorAuthMethod
|
||||||
}: TGetIdentityPrivilegeDetailsDTO) => {
|
}: TGetIdentityPrivilegeDetailsDTO) => {
|
||||||
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findById(privilegeId);
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
const projectId = project.id;
|
||||||
const identityProjectMembership = await identityProjectDAL.findById(identityPrivilege.projectMembershipId);
|
|
||||||
if (!identityProjectMembership) throw new BadRequestError({ message: `Failed to find identity` });
|
|
||||||
|
|
||||||
|
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||||
|
if (!identityProjectMembership)
|
||||||
|
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
@@ -218,31 +247,31 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
|
||||||
const { permission: identityRolePermission } = await permissionService.getProjectPermission(
|
|
||||||
ActorType.IDENTITY,
|
const identityPrivilege = await identityProjectAdditionalPrivilegeDAL.findOne({
|
||||||
identityProjectMembership.identityId,
|
slug,
|
||||||
identityProjectMembership.projectId,
|
projectMembershipId: identityProjectMembership.id
|
||||||
actorAuthMethod,
|
});
|
||||||
actorOrgId
|
if (!identityPrivilege) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
||||||
);
|
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
|
||||||
if (!hasRequiredPriviledges)
|
|
||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
|
||||||
|
|
||||||
return identityPrivilege;
|
return identityPrivilege;
|
||||||
};
|
};
|
||||||
|
|
||||||
const listIdentityProjectPrivileges = async ({
|
const listIdentityProjectPrivileges = async ({
|
||||||
projectId,
|
|
||||||
identityId,
|
identityId,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
actorAuthMethod
|
actorAuthMethod,
|
||||||
|
projectSlug
|
||||||
}: TListIdentityPrivilegesDTO) => {
|
}: TListIdentityPrivilegesDTO) => {
|
||||||
const identityProjectMembership = await identityProjectDAL.findOne({ projectId, identityId });
|
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||||
if (!identityProjectMembership) throw new BadRequestError({ message: `Failed to find identity` });
|
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||||
|
const projectId = project.id;
|
||||||
|
|
||||||
|
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
|
||||||
|
if (!identityProjectMembership)
|
||||||
|
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
actorId,
|
actorId,
|
||||||
@@ -251,29 +280,18 @@ export const identityProjectAdditionalPrivilegeServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
|
||||||
const { permission: identityRolePermission } = await permissionService.getProjectPermission(
|
|
||||||
ActorType.IDENTITY,
|
|
||||||
identityProjectMembership.identityId,
|
|
||||||
identityProjectMembership.projectId,
|
|
||||||
actorAuthMethod,
|
|
||||||
actorOrgId
|
|
||||||
);
|
|
||||||
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, identityRolePermission);
|
|
||||||
if (!hasRequiredPriviledges)
|
|
||||||
throw new ForbiddenRequestError({ message: "Failed to delete more privileged identity" });
|
|
||||||
|
|
||||||
const identityPrivileges = await identityProjectAdditionalPrivilegeDAL.find({
|
const identityPrivileges = await identityProjectAdditionalPrivilegeDAL.find({
|
||||||
projectMembershipId: identityProjectMembership.id
|
projectMembershipId: identityProjectMembership.id
|
||||||
});
|
});
|
||||||
if (!identityPrivileges) throw new BadRequestError({ message: "Identity additional privilege not found" });
|
|
||||||
return identityPrivileges;
|
return identityPrivileges;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
create,
|
create,
|
||||||
updateById,
|
updateBySlug,
|
||||||
deleteById,
|
deleteBySlug,
|
||||||
getPrivilegeDetailsById,
|
getPrivilegeDetailsBySlug,
|
||||||
listIdentityProjectPrivileges
|
listIdentityProjectPrivileges
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
+30
-21
@@ -4,19 +4,16 @@ export enum IdentityProjectAdditionalPrivilegeTemporaryMode {
|
|||||||
Relative = "relative"
|
Relative = "relative"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TCreateIdentityPrivilegeDTO = (
|
export type TCreateIdentityPrivilegeDTO = {
|
||||||
|
permissions: unknown;
|
||||||
|
identityId: string;
|
||||||
|
projectSlug: string;
|
||||||
|
slug: string;
|
||||||
|
} & (
|
||||||
| {
|
| {
|
||||||
permissions: unknown;
|
|
||||||
identityId: string;
|
|
||||||
projectId: string;
|
|
||||||
slug: string;
|
|
||||||
isTemporary: false;
|
isTemporary: false;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
permissions: unknown;
|
|
||||||
identityId: string;
|
|
||||||
projectId: string;
|
|
||||||
slug: string;
|
|
||||||
isTemporary: true;
|
isTemporary: true;
|
||||||
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative;
|
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative;
|
||||||
temporaryRange: string;
|
temporaryRange: string;
|
||||||
@@ -25,21 +22,33 @@ export type TCreateIdentityPrivilegeDTO = (
|
|||||||
) &
|
) &
|
||||||
Omit<TProjectPermission, "projectId">;
|
Omit<TProjectPermission, "projectId">;
|
||||||
|
|
||||||
export type TUpdateIdentityPrivilegeDTO = { privilegeId: string } & Omit<TProjectPermission, "projectId"> &
|
export type TUpdateIdentityPrivilegeDTO = { slug: string; identityId: string; projectSlug: string } & Omit<
|
||||||
Partial<{
|
TProjectPermission,
|
||||||
permissions: unknown;
|
"projectId"
|
||||||
slug: string;
|
> & {
|
||||||
isTemporary: boolean;
|
data: Partial<{
|
||||||
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative;
|
permissions: unknown;
|
||||||
temporaryRange: string;
|
slug: string;
|
||||||
temporaryAccessStartTime: string;
|
isTemporary: boolean;
|
||||||
}>;
|
temporaryMode: IdentityProjectAdditionalPrivilegeTemporaryMode.Relative;
|
||||||
|
temporaryRange: string;
|
||||||
|
temporaryAccessStartTime: string;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
export type TDeleteIdentityPrivilegeDTO = Omit<TProjectPermission, "projectId"> & { privilegeId: string };
|
export type TDeleteIdentityPrivilegeDTO = Omit<TProjectPermission, "projectId"> & {
|
||||||
|
slug: string;
|
||||||
|
identityId: string;
|
||||||
|
projectSlug: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type TGetIdentityPrivilegeDetailsDTO = Omit<TProjectPermission, "projectId"> & { privilegeId: string };
|
export type TGetIdentityPrivilegeDetailsDTO = Omit<TProjectPermission, "projectId"> & {
|
||||||
|
slug: string;
|
||||||
|
identityId: string;
|
||||||
|
projectSlug: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type TListIdentityPrivilegesDTO = Omit<TProjectPermission, "projectId"> & {
|
export type TListIdentityPrivilegesDTO = Omit<TProjectPermission, "projectId"> & {
|
||||||
identityId: string;
|
identityId: string;
|
||||||
projectId: string;
|
projectSlug: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!permission?.[0]) return undefined;
|
||||||
// when introducting cron mode change it here
|
// when introducting cron mode change it here
|
||||||
const activeRoles = permission?.[0]?.roles?.filter(
|
const activeRoles = permission?.[0]?.roles?.filter(
|
||||||
({ isTemporary, temporaryAccessEndTime }) =>
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
@@ -155,9 +157,7 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
);
|
);
|
||||||
|
|
||||||
return permission?.[0]
|
return { ...permission[0], roles: activeRoles, additionalPrivileges: activeAdditionalPrivileges };
|
||||||
? { ...permission[0], roles: activeRoles, additionalPrivileges: activeAdditionalPrivileges }
|
|
||||||
: undefined;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new DatabaseError({ error, name: "GetProjectPermission" });
|
throw new DatabaseError({ error, name: "GetProjectPermission" });
|
||||||
}
|
}
|
||||||
@@ -176,6 +176,11 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
`${TableName.IdentityProjectMembershipRole}.customRoleId`,
|
`${TableName.IdentityProjectMembershipRole}.customRoleId`,
|
||||||
`${TableName.ProjectRoles}.id`
|
`${TableName.ProjectRoles}.id`
|
||||||
)
|
)
|
||||||
|
.leftJoin(
|
||||||
|
TableName.IdentityProjectAdditionalPrivilege,
|
||||||
|
`${TableName.IdentityProjectAdditionalPrivilege}.projectMembershipId`,
|
||||||
|
`${TableName.IdentityProjectMembership}.id`
|
||||||
|
)
|
||||||
.join(
|
.join(
|
||||||
// Join the Project table to later select orgId
|
// Join the Project table to later select orgId
|
||||||
TableName.Project,
|
TableName.Project,
|
||||||
@@ -191,9 +196,28 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("role").withSchema(TableName.IdentityProjectMembership).as("oldRoleField"),
|
db.ref("role").withSchema(TableName.IdentityProjectMembership).as("oldRoleField"),
|
||||||
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"),
|
db.ref("createdAt").withSchema(TableName.IdentityProjectMembership).as("membershipCreatedAt"),
|
||||||
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"),
|
db.ref("updatedAt").withSchema(TableName.IdentityProjectMembership).as("membershipUpdatedAt"),
|
||||||
db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug")
|
db.ref("slug").withSchema(TableName.ProjectRoles).as("customRoleSlug"),
|
||||||
)
|
db.ref("permissions").withSchema(TableName.ProjectRoles),
|
||||||
.select("permissions");
|
db.ref("id").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApId"),
|
||||||
|
db.ref("permissions").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApPermissions"),
|
||||||
|
db
|
||||||
|
.ref("temporaryMode")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryMode"),
|
||||||
|
db.ref("isTemporary").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApIsTemporary"),
|
||||||
|
db
|
||||||
|
.ref("temporaryRange")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryRange"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessStartTime")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryAccessStartTime"),
|
||||||
|
db
|
||||||
|
.ref("temporaryAccessEndTime")
|
||||||
|
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
||||||
|
.as("identityApTemporaryAccessEndTime")
|
||||||
|
);
|
||||||
|
|
||||||
const permission = sqlNestRelationships({
|
const permission = sqlNestRelationships({
|
||||||
data: docs,
|
data: docs,
|
||||||
@@ -218,16 +242,44 @@ export const permissionDALFactory = (db: TDbClient) => {
|
|||||||
permissions: z.unknown(),
|
permissions: z.unknown(),
|
||||||
customRoleSlug: z.string().optional().nullable()
|
customRoleSlug: z.string().optional().nullable()
|
||||||
}).parse(data)
|
}).parse(data)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "identityApId",
|
||||||
|
label: "additionalPrivileges" as const,
|
||||||
|
mapper: ({
|
||||||
|
identityApId,
|
||||||
|
identityApPermissions,
|
||||||
|
identityApIsTemporary,
|
||||||
|
identityApTemporaryMode,
|
||||||
|
identityApTemporaryRange,
|
||||||
|
identityApTemporaryAccessEndTime,
|
||||||
|
identityApTemporaryAccessStartTime
|
||||||
|
}) => ({
|
||||||
|
id: identityApId,
|
||||||
|
permissions: identityApPermissions,
|
||||||
|
temporaryRange: identityApTemporaryRange,
|
||||||
|
temporaryMode: identityApTemporaryMode,
|
||||||
|
temporaryAccessEndTime: identityApTemporaryAccessEndTime,
|
||||||
|
temporaryAccessStartTime: identityApTemporaryAccessStartTime,
|
||||||
|
isTemporary: identityApIsTemporary
|
||||||
|
})
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!permission?.[0]) return undefined;
|
||||||
|
|
||||||
// when introducting cron mode change it here
|
// when introducting cron mode change it here
|
||||||
const activeRoles = permission?.[0]?.roles.filter(
|
const activeRoles = permission?.[0]?.roles.filter(
|
||||||
({ isTemporary, temporaryAccessEndTime }) =>
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
);
|
);
|
||||||
return permission?.[0] ? { ...permission[0], roles: activeRoles } : undefined;
|
const activeAdditionalPrivileges = permission?.[0]?.additionalPrivileges?.filter(
|
||||||
|
({ isTemporary, temporaryAccessEndTime }) =>
|
||||||
|
!isTemporary || (isTemporary && temporaryAccessEndTime && new Date() < temporaryAccessEndTime)
|
||||||
|
);
|
||||||
|
|
||||||
|
return { ...permission[0], roles: activeRoles, additionalPrivileges: activeAdditionalPrivileges };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new DatabaseError({ error, name: "GetProjectIdentityPermission" });
|
throw new DatabaseError({ error, name: "GetProjectIdentityPermission" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,8 +238,16 @@ export const permissionServiceFactory = ({
|
|||||||
throw new UnauthorizedError({ name: "You are not a member of this organization" });
|
throw new UnauthorizedError({ name: "You are not a member of this organization" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rolePermissions =
|
||||||
|
identityProjectPermission.roles?.map(({ role, permissions }) => ({ role, permissions })) || [];
|
||||||
|
const additionalPrivileges =
|
||||||
|
identityProjectPermission.additionalPrivileges?.map(({ permissions }) => ({
|
||||||
|
role: ProjectMembershipRole.Custom,
|
||||||
|
permissions
|
||||||
|
})) || [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
permission: buildProjectPermission(identityProjectPermission.roles),
|
permission: buildProjectPermission(rolePermissions.concat(additionalPrivileges)),
|
||||||
membership: identityProjectPermission,
|
membership: identityProjectPermission,
|
||||||
hasRole: (role: string) =>
|
hasRole: (role: string) =>
|
||||||
identityProjectPermission.roles.findIndex(
|
identityProjectPermission.roles.findIndex(
|
||||||
|
|||||||
@@ -560,6 +560,7 @@ export const registerRoutes = async (
|
|||||||
projectRoleDAL
|
projectRoleDAL
|
||||||
});
|
});
|
||||||
const identityProjectAdditionalPrivilegeService = identityProjectAdditionalPrivilegeServiceFactory({
|
const identityProjectAdditionalPrivilegeService = identityProjectAdditionalPrivilegeServiceFactory({
|
||||||
|
projectDAL,
|
||||||
identityProjectAdditionalPrivilegeDAL,
|
identityProjectAdditionalPrivilegeDAL,
|
||||||
permissionService,
|
permissionService,
|
||||||
identityProjectDAL
|
identityProjectDAL
|
||||||
|
|||||||
@@ -156,20 +156,6 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
|||||||
identityId: z.string(),
|
identityId: z.string(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
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(
|
roles: z.array(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
|
|||||||
@@ -47,29 +47,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("isTemporary").withSchema(TableName.IdentityProjectMembershipRole),
|
db.ref("isTemporary").withSchema(TableName.IdentityProjectMembershipRole),
|
||||||
db.ref("temporaryRange").withSchema(TableName.IdentityProjectMembershipRole),
|
db.ref("temporaryRange").withSchema(TableName.IdentityProjectMembershipRole),
|
||||||
db.ref("temporaryAccessStartTime").withSchema(TableName.IdentityProjectMembershipRole),
|
db.ref("temporaryAccessStartTime").withSchema(TableName.IdentityProjectMembershipRole),
|
||||||
db.ref("temporaryAccessEndTime").withSchema(TableName.IdentityProjectMembershipRole),
|
db.ref("temporaryAccessEndTime").withSchema(TableName.IdentityProjectMembershipRole)
|
||||||
db.ref("id").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApId"),
|
|
||||||
db.ref("name").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApName"),
|
|
||||||
db.ref("description").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApDescription"),
|
|
||||||
db.ref("slug").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApSlug"),
|
|
||||||
db
|
|
||||||
.ref("temporaryMode")
|
|
||||||
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
|
||||||
.as("identityApTemporaryMode"),
|
|
||||||
db.ref("isTemporary").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApIsTemporary"),
|
|
||||||
db.ref("createdAt").withSchema(TableName.IdentityProjectAdditionalPrivilege).as("identityApCreatedAt"),
|
|
||||||
db
|
|
||||||
.ref("temporaryRange")
|
|
||||||
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
|
||||||
.as("identityApTemporaryRange"),
|
|
||||||
db
|
|
||||||
.ref("temporaryAccessStartTime")
|
|
||||||
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
|
||||||
.as("identityApTemporaryAccessStartTime"),
|
|
||||||
db
|
|
||||||
.ref("temporaryAccessEndTime")
|
|
||||||
.withSchema(TableName.IdentityProjectAdditionalPrivilege)
|
|
||||||
.as("identityApTemporaryAccessEndTime")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const members = sqlNestRelationships({
|
const members = sqlNestRelationships({
|
||||||
@@ -113,33 +91,6 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
temporaryAccessStartTime,
|
temporaryAccessStartTime,
|
||||||
isTemporary
|
isTemporary
|
||||||
})
|
})
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "additionalPrivileges" as const,
|
|
||||||
key: "identityApId",
|
|
||||||
mapper: ({
|
|
||||||
identityApId,
|
|
||||||
identityApDescription,
|
|
||||||
identityApName,
|
|
||||||
identityApSlug,
|
|
||||||
identityApIsTemporary,
|
|
||||||
identityApTemporaryMode,
|
|
||||||
identityApTemporaryRange,
|
|
||||||
identityApCreatedAt,
|
|
||||||
identityApTemporaryAccessEndTime,
|
|
||||||
identityApTemporaryAccessStartTime
|
|
||||||
}) => ({
|
|
||||||
id: identityApId,
|
|
||||||
name: identityApName,
|
|
||||||
description: identityApDescription,
|
|
||||||
slug: identityApSlug,
|
|
||||||
temporaryRange: identityApTemporaryRange,
|
|
||||||
temporaryMode: identityApTemporaryMode,
|
|
||||||
temporaryAccessEndTime: identityApTemporaryAccessEndTime,
|
|
||||||
temporaryAccessStartTime: identityApTemporaryAccessStartTime,
|
|
||||||
isTemporary: identityApIsTemporary,
|
|
||||||
createdAt: identityApCreatedAt
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user