mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 20:27:12 +00:00
feat: completed new role service
This commit is contained in:
@@ -2,7 +2,7 @@ import { MongoAbility } from "@casl/ability";
|
|||||||
import { MongoQuery } from "@ucast/mongo2js";
|
import { MongoQuery } from "@ucast/mongo2js";
|
||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { ActionProjectType, TMemberships } from "@app/db/schemas";
|
import { AccessScope, AccessScopeData, ActionProjectType, TMemberships } from "@app/db/schemas";
|
||||||
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
import { OrgPermissionSet } from "./org-permission";
|
import { OrgPermissionSet } from "./org-permission";
|
||||||
@@ -49,6 +49,14 @@ export type TGetProjectPermissionArg = {
|
|||||||
actionProjectType: ActionProjectType;
|
actionProjectType: ActionProjectType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TGetOrgPermissionArg = {
|
||||||
|
actor: ActorType;
|
||||||
|
actorId: string;
|
||||||
|
orgId: string;
|
||||||
|
actorAuthMethod: ActorAuthMethod;
|
||||||
|
actorOrgId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type TPermissionServiceFactory = {
|
export type TPermissionServiceFactory = {
|
||||||
getOrgPermission: (
|
getOrgPermission: (
|
||||||
type: ActorType,
|
type: ActorType,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { AccessScope } from "@app/db/schemas";
|
||||||
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
|
||||||
|
import { TRoleScopeFactory } from "../role-types";
|
||||||
|
|
||||||
|
type TNamespaceRoleScopeFactoryDep = {
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export const newNamespaceRoleFactory = (_dto: TNamespaceRoleScopeFactoryDep): TRoleScopeFactory => {
|
||||||
|
const onCreateRoleGuard: TRoleScopeFactory["onCreateRoleGuard"] = async () => {};
|
||||||
|
|
||||||
|
const onUpdateRoleGuard: TRoleScopeFactory["onUpdateRoleGuard"] = async () => {};
|
||||||
|
|
||||||
|
const onDeleteRoleGuard: TRoleScopeFactory["onDeleteRoleGuard"] = async () => {};
|
||||||
|
|
||||||
|
const onListRoleGuard: TRoleScopeFactory["onListRoleGuard"] = async () => {};
|
||||||
|
|
||||||
|
const onGetRoleByIdGuard: TRoleScopeFactory["onGetRoleByIdGuard"] = async () => {};
|
||||||
|
|
||||||
|
const onGetRoleBySlugGuard: TRoleScopeFactory["onGetRoleBySlugGuard"] = async () => {};
|
||||||
|
|
||||||
|
const getScopeField: TRoleScopeFactory["getScopeField"] = (dto) => {
|
||||||
|
if (dto.scope === AccessScope.Namespace) {
|
||||||
|
return { key: "namespaceId" as const, value: dto.namespaceId };
|
||||||
|
}
|
||||||
|
throw new BadRequestError({ message: "Invalid scope provided for the factory" });
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
onCreateRoleGuard,
|
||||||
|
onUpdateRoleGuard,
|
||||||
|
onDeleteRoleGuard,
|
||||||
|
onListRoleGuard,
|
||||||
|
onGetRoleByIdGuard,
|
||||||
|
onGetRoleBySlugGuard,
|
||||||
|
getScopeField
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
|
||||||
|
import { AccessScope } from "@app/db/schemas";
|
||||||
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
|
||||||
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
|
||||||
|
import { TRoleScopeFactory } from "../role-types";
|
||||||
|
|
||||||
|
type TOrgRoleScopeFactoryDep = {
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const newOrgRoleFactory = ({ permissionService }: TOrgRoleScopeFactoryDep): TRoleScopeFactory => {
|
||||||
|
const getScopeField: TRoleScopeFactory["getScopeField"] = (dto) => {
|
||||||
|
if (dto.scope === AccessScope.Organization) {
|
||||||
|
return { key: "orgId" as const, value: dto.orgId };
|
||||||
|
}
|
||||||
|
throw new BadRequestError({ message: "Invalid scope provided for the factory" });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCreateRoleGuard: TRoleScopeFactory["onCreateRoleGuard"] = async (dto) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.permission.type,
|
||||||
|
dto.permission.id,
|
||||||
|
dto.permission.orgId,
|
||||||
|
dto.permission.authMethod,
|
||||||
|
dto.permission.orgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onUpdateRoleGuard: TRoleScopeFactory["onUpdateRoleGuard"] = async (dto) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.permission.type,
|
||||||
|
dto.permission.id,
|
||||||
|
dto.permission.orgId,
|
||||||
|
dto.permission.authMethod,
|
||||||
|
dto.permission.orgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteRoleGuard: TRoleScopeFactory["onDeleteRoleGuard"] = async (dto) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.permission.type,
|
||||||
|
dto.permission.id,
|
||||||
|
dto.permission.orgId,
|
||||||
|
dto.permission.authMethod,
|
||||||
|
dto.permission.orgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onListRoleGuard: TRoleScopeFactory["onListRoleGuard"] = async (dto) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.permission.type,
|
||||||
|
dto.permission.id,
|
||||||
|
dto.permission.orgId,
|
||||||
|
dto.permission.authMethod,
|
||||||
|
dto.permission.orgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onGetRoleByIdGuard: TRoleScopeFactory["onGetRoleByIdGuard"] = async (dto) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.permission.type,
|
||||||
|
dto.permission.id,
|
||||||
|
dto.permission.orgId,
|
||||||
|
dto.permission.authMethod,
|
||||||
|
dto.permission.orgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onGetRoleBySlugGuard: TRoleScopeFactory["onGetRoleBySlugGuard"] = async (dto) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
dto.permission.type,
|
||||||
|
dto.permission.id,
|
||||||
|
dto.permission.orgId,
|
||||||
|
dto.permission.authMethod,
|
||||||
|
dto.permission.orgId
|
||||||
|
);
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
onCreateRoleGuard,
|
||||||
|
onUpdateRoleGuard,
|
||||||
|
onDeleteRoleGuard,
|
||||||
|
onListRoleGuard,
|
||||||
|
onGetRoleByIdGuard,
|
||||||
|
onGetRoleBySlugGuard,
|
||||||
|
getScopeField
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
|
||||||
|
import { AccessScope, ActionProjectType } from "@app/db/schemas";
|
||||||
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||||
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
|
||||||
|
import { TRoleScopeFactory } from "../role-types";
|
||||||
|
|
||||||
|
type TProjectRoleScopeFactoryDep = {
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const newProjectRoleFactory = ({ permissionService }: TProjectRoleScopeFactoryDep): TRoleScopeFactory => {
|
||||||
|
const getScopeField: TRoleScopeFactory["getScopeField"] = (dto) => {
|
||||||
|
if (dto.scope === AccessScope.Project) {
|
||||||
|
return { key: "projectId" as const, value: dto.projectId };
|
||||||
|
}
|
||||||
|
throw new BadRequestError({ message: "Invalid scope provided for the factory" });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCreateRoleGuard: TRoleScopeFactory["onCreateRoleGuard"] = async (dto) => {
|
||||||
|
const scope = getScopeField(dto.scopeData);
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: dto.permission.type,
|
||||||
|
actorId: dto.permission.id,
|
||||||
|
actionProjectType: ActionProjectType.Any,
|
||||||
|
actorAuthMethod: dto.permission.authMethod,
|
||||||
|
projectId: scope.value,
|
||||||
|
actorOrgId: dto.permission.orgId
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onUpdateRoleGuard: TRoleScopeFactory["onUpdateRoleGuard"] = async (dto) => {
|
||||||
|
const scope = getScopeField(dto.scopeData);
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: dto.permission.type,
|
||||||
|
actorId: dto.permission.id,
|
||||||
|
actionProjectType: ActionProjectType.Any,
|
||||||
|
actorAuthMethod: dto.permission.authMethod,
|
||||||
|
projectId: scope.value,
|
||||||
|
actorOrgId: dto.permission.orgId
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteRoleGuard: TRoleScopeFactory["onDeleteRoleGuard"] = async (dto) => {
|
||||||
|
const scope = getScopeField(dto.scopeData);
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: dto.permission.type,
|
||||||
|
actorId: dto.permission.id,
|
||||||
|
actionProjectType: ActionProjectType.Any,
|
||||||
|
actorAuthMethod: dto.permission.authMethod,
|
||||||
|
projectId: scope.value,
|
||||||
|
actorOrgId: dto.permission.orgId
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onListRoleGuard: TRoleScopeFactory["onListRoleGuard"] = async (dto) => {
|
||||||
|
const scope = getScopeField(dto.scopeData);
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: dto.permission.type,
|
||||||
|
actorId: dto.permission.id,
|
||||||
|
actionProjectType: ActionProjectType.Any,
|
||||||
|
actorAuthMethod: dto.permission.authMethod,
|
||||||
|
projectId: scope.value,
|
||||||
|
actorOrgId: dto.permission.orgId
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onGetRoleByIdGuard: TRoleScopeFactory["onGetRoleByIdGuard"] = async (dto) => {
|
||||||
|
const scope = getScopeField(dto.scopeData);
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: dto.permission.type,
|
||||||
|
actorId: dto.permission.id,
|
||||||
|
actionProjectType: ActionProjectType.Any,
|
||||||
|
actorAuthMethod: dto.permission.authMethod,
|
||||||
|
projectId: scope.value,
|
||||||
|
actorOrgId: dto.permission.orgId
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onGetRoleBySlugGuard: TRoleScopeFactory["onGetRoleBySlugGuard"] = async (dto) => {
|
||||||
|
const scope = getScopeField(dto.scopeData);
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: dto.permission.type,
|
||||||
|
actorId: dto.permission.id,
|
||||||
|
actionProjectType: ActionProjectType.Any,
|
||||||
|
actorAuthMethod: dto.permission.authMethod,
|
||||||
|
projectId: scope.value,
|
||||||
|
actorOrgId: dto.permission.orgId
|
||||||
|
});
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
onCreateRoleGuard,
|
||||||
|
onUpdateRoleGuard,
|
||||||
|
onDeleteRoleGuard,
|
||||||
|
onListRoleGuard,
|
||||||
|
onGetRoleByIdGuard,
|
||||||
|
onGetRoleBySlugGuard,
|
||||||
|
getScopeField
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { TDbClient } from "@app/db";
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
import { ormify } from "@app/lib/knex";
|
||||||
|
|
||||||
|
export type TRoleDALFactory = ReturnType<typeof roleDALFactory>;
|
||||||
|
|
||||||
|
export const roleDALFactory = (db: TDbClient) => {
|
||||||
|
const orm = ormify(db, TableName.Role);
|
||||||
|
return orm;
|
||||||
|
};
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
import { AccessScope, TableName } from "@app/db/schemas";
|
||||||
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service-types";
|
||||||
|
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
|
import { validateHandlebarTemplate } from "@app/lib/template/validate-handlebars";
|
||||||
|
|
||||||
|
import { newNamespaceRoleFactory } from "./namespace/namespace-role-factory";
|
||||||
|
import { newOrgRoleFactory } from "./org/org-role-factory";
|
||||||
|
import { newProjectRoleFactory } from "./project/project-role-factory";
|
||||||
|
import { TRoleDALFactory } from "./role-dal";
|
||||||
|
import {
|
||||||
|
TCreateRoleDTO,
|
||||||
|
TDeleteRoleDTO,
|
||||||
|
TGetRoleByIdDTO,
|
||||||
|
TGetRoleBySlugDTO,
|
||||||
|
TListRoleDTO,
|
||||||
|
TUpdateRoleDTO
|
||||||
|
} from "./role-types";
|
||||||
|
|
||||||
|
type TRoleServiceFactoryDep = {
|
||||||
|
roleDAL: TRoleDALFactory;
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TRoleServiceFactory = ReturnType<typeof roleServiceFactory>;
|
||||||
|
|
||||||
|
export const roleServiceFactory = ({ roleDAL, permissionService }: TRoleServiceFactoryDep) => {
|
||||||
|
const orgRoleFactory = newOrgRoleFactory({
|
||||||
|
permissionService
|
||||||
|
});
|
||||||
|
const projectRoleFactory = newProjectRoleFactory({
|
||||||
|
permissionService
|
||||||
|
});
|
||||||
|
const namespaceRoleFactory = newNamespaceRoleFactory({
|
||||||
|
permissionService
|
||||||
|
});
|
||||||
|
const scopeFactory = {
|
||||||
|
[AccessScope.Organization]: orgRoleFactory,
|
||||||
|
[AccessScope.Project]: projectRoleFactory,
|
||||||
|
[AccessScope.Namespace]: namespaceRoleFactory
|
||||||
|
};
|
||||||
|
|
||||||
|
const createRole = async (dto: TCreateRoleDTO) => {
|
||||||
|
const { data, scopeData } = dto;
|
||||||
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
await factory.onCreateRoleGuard(dto);
|
||||||
|
|
||||||
|
validateHandlebarTemplate("Role Creation", JSON.stringify(data.permissions || []), {
|
||||||
|
allowedExpressions: (val) => val.includes("identity.")
|
||||||
|
});
|
||||||
|
|
||||||
|
const scope = factory.getScopeField(scopeData);
|
||||||
|
const role = await roleDAL.create({
|
||||||
|
name: data.name,
|
||||||
|
description: data.description,
|
||||||
|
slug: data.slug,
|
||||||
|
permissions: data.permissions,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...role, [scope.key]: scope.value };
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateRole = async (dto: TUpdateRoleDTO) => {
|
||||||
|
const { data, scopeData } = dto;
|
||||||
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
const scope = factory.getScopeField(scopeData);
|
||||||
|
|
||||||
|
await factory.onUpdateRoleGuard(dto);
|
||||||
|
|
||||||
|
const existingRole = await roleDAL.findOne({
|
||||||
|
id: dto.selector.id,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
if (!existingRole) throw new NotFoundError({ message: `Role with ${dto.selector.id} not found` });
|
||||||
|
|
||||||
|
if (data.slug) {
|
||||||
|
const existingSlug = await roleDAL.findOne({
|
||||||
|
slug: data.slug,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
if (existingSlug && existingRole.id !== existingSlug.id)
|
||||||
|
throw new BadRequestError({ message: `Role with ${data.slug} not found` });
|
||||||
|
}
|
||||||
|
|
||||||
|
validateHandlebarTemplate("Role Update", JSON.stringify(data.permissions || []), {
|
||||||
|
allowedExpressions: (val) => val.includes("identity.")
|
||||||
|
});
|
||||||
|
|
||||||
|
const role = await roleDAL.updateById(existingRole.id, {
|
||||||
|
name: data?.name,
|
||||||
|
description: data?.description,
|
||||||
|
slug: data?.slug,
|
||||||
|
permissions: data?.permissions
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...role, [scope.key]: scope.value };
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteRole = async (dto: TDeleteRoleDTO) => {
|
||||||
|
const { scopeData } = dto;
|
||||||
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
const scope = factory.getScopeField(scopeData);
|
||||||
|
await factory.onDeleteRoleGuard(dto);
|
||||||
|
|
||||||
|
const existingRole = await roleDAL.findOne({
|
||||||
|
id: dto.selector.id,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
if (!existingRole) throw new NotFoundError({ message: `Role with ${dto.selector.id} not found` });
|
||||||
|
|
||||||
|
const [role] = await roleDAL.delete({
|
||||||
|
id: existingRole.id,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
|
||||||
|
return { ...role, [scope.key]: scope.value };
|
||||||
|
};
|
||||||
|
|
||||||
|
const listRoles = async (dto: TListRoleDTO) => {
|
||||||
|
const { scopeData } = dto;
|
||||||
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
|
||||||
|
await factory.onListRoleGuard(dto);
|
||||||
|
|
||||||
|
const scope = factory.getScopeField(scopeData);
|
||||||
|
const roles = await roleDAL.find(
|
||||||
|
{
|
||||||
|
[scope.key]: scope.value
|
||||||
|
},
|
||||||
|
{ limit: dto.data.limit, offset: dto.data.offset, sort: [[`${TableName.Role}.slug` as "slug", "asc"]] }
|
||||||
|
);
|
||||||
|
|
||||||
|
return { roles };
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRoleById = async (dto: TGetRoleByIdDTO) => {
|
||||||
|
const { scopeData, selector } = dto;
|
||||||
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
|
||||||
|
await factory.onGetRoleByIdGuard(dto);
|
||||||
|
|
||||||
|
const scope = factory.getScopeField(scopeData);
|
||||||
|
const role = await roleDAL.findOne({
|
||||||
|
id: selector.id,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
if (!role) throw new NotFoundError({ message: `Role with id ${dto.selector.id} not found` });
|
||||||
|
|
||||||
|
return { ...role, [scope.key]: scope.value };
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRoleBySlug = async (dto: TGetRoleBySlugDTO) => {
|
||||||
|
const { scopeData, selector } = dto;
|
||||||
|
const factory = scopeFactory[scopeData.scope];
|
||||||
|
|
||||||
|
await factory.onGetRoleBySlugGuard(dto);
|
||||||
|
|
||||||
|
const scope = factory.getScopeField(scopeData);
|
||||||
|
const role = await roleDAL.findOne({
|
||||||
|
slug: selector.slug,
|
||||||
|
[scope.key]: scope.value
|
||||||
|
});
|
||||||
|
if (!role) throw new NotFoundError({ message: `Role with slug ${dto.selector.slug} not found` });
|
||||||
|
|
||||||
|
return { ...role, [scope.key]: scope.value };
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
createRole,
|
||||||
|
updateRole,
|
||||||
|
deleteRole,
|
||||||
|
listRoles,
|
||||||
|
getRoleById,
|
||||||
|
getRoleBySlug
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { AccessScopeData } from "@app/db/schemas";
|
||||||
|
import { OrgServiceActor } from "@app/lib/types";
|
||||||
|
|
||||||
|
export interface TRoleScopeFactory {
|
||||||
|
onCreateRoleGuard: (arg: TCreateRoleDTO) => Promise<void>;
|
||||||
|
onUpdateRoleGuard: (arg: TUpdateRoleDTO) => Promise<void>;
|
||||||
|
onDeleteRoleGuard: (arg: TDeleteRoleDTO) => Promise<void>;
|
||||||
|
onListRoleGuard: (arg: TListRoleDTO) => Promise<void>;
|
||||||
|
onGetRoleByIdGuard: (arg: TGetRoleByIdDTO) => Promise<void>;
|
||||||
|
onGetRoleBySlugGuard: (arg: TGetRoleBySlugDTO) => Promise<void>;
|
||||||
|
getScopeField: (scope: AccessScopeData) => { key: "orgId" | "namespaceId" | "projectId"; value: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TCreateRoleDTO = {
|
||||||
|
permission: OrgServiceActor;
|
||||||
|
scopeData: AccessScopeData;
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
slug: string;
|
||||||
|
permissions: unknown;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TUpdateRoleDTO = {
|
||||||
|
permission: OrgServiceActor;
|
||||||
|
scopeData: AccessScopeData;
|
||||||
|
selector: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
data: Partial<{
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
slug: string;
|
||||||
|
permissions: unknown;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TListRoleDTO = {
|
||||||
|
permission: OrgServiceActor;
|
||||||
|
scopeData: AccessScopeData;
|
||||||
|
data: {
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TDeleteRoleDTO = {
|
||||||
|
permission: OrgServiceActor;
|
||||||
|
scopeData: AccessScopeData;
|
||||||
|
selector: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TGetRoleByIdDTO = {
|
||||||
|
permission: OrgServiceActor;
|
||||||
|
scopeData: AccessScopeData;
|
||||||
|
selector: {
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TGetRoleBySlugDTO = {
|
||||||
|
permission: OrgServiceActor;
|
||||||
|
scopeData: AccessScopeData;
|
||||||
|
selector: {
|
||||||
|
slug: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user