mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +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 { 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 { OrgPermissionSet } from "./org-permission";
|
||||
@@ -49,6 +49,14 @@ export type TGetProjectPermissionArg = {
|
||||
actionProjectType: ActionProjectType;
|
||||
};
|
||||
|
||||
export type TGetOrgPermissionArg = {
|
||||
actor: ActorType;
|
||||
actorId: string;
|
||||
orgId: string;
|
||||
actorAuthMethod: ActorAuthMethod;
|
||||
actorOrgId?: string;
|
||||
};
|
||||
|
||||
export type TPermissionServiceFactory = {
|
||||
getOrgPermission: (
|
||||
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
|
||||
};
|
||||
};
|
||||
97
backend/src/services/role/org/org-role-factory.ts
Normal file
97
backend/src/services/role/org/org-role-factory.ts
Normal file
@@ -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
|
||||
};
|
||||
};
|
||||
109
backend/src/services/role/project/project-role-factory.ts
Normal file
109
backend/src/services/role/project/project-role-factory.ts
Normal file
@@ -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
|
||||
};
|
||||
};
|
||||
10
backend/src/services/role/role-dal.ts
Normal file
10
backend/src/services/role/role-dal.ts
Normal file
@@ -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;
|
||||
};
|
||||
176
backend/src/services/role/role-service.ts
Normal file
176
backend/src/services/role/role-service.ts
Normal file
@@ -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
|
||||
};
|
||||
};
|
||||
70
backend/src/services/role/role-types.ts
Normal file
70
backend/src/services/role/role-types.ts
Normal file
@@ -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