Feat: Scoped JWT to organization, add actorAuthMethod to services

This commit is contained in:
Daniel Hougaard
2024-03-12 14:25:40 +01:00
parent fe638ce2c1
commit 900facdb36
14 changed files with 512 additions and 84 deletions

View File

@@ -37,10 +37,17 @@ export const projectBotServiceFactory = ({
projectId,
actorOrgId,
privateKey,
actorAuthMethod,
botKey,
publicKey
}: TFindBotByProjectIdDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const bot = await projectBotDAL.transaction(async (tx) => {
@@ -88,11 +95,25 @@ export const projectBotServiceFactory = ({
}
};
const setBotActiveState = async ({ actor, botId, botKey, actorId, actorOrgId, isActive }: TSetActiveStateDTO) => {
const setBotActiveState = async ({
actor,
botId,
botKey,
actorId,
actorOrgId,
actorAuthMethod,
isActive
}: TSetActiveStateDTO) => {
const bot = await projectBotDAL.findById(botId);
if (!bot) throw new BadRequestError({ message: "Bot not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, bot.projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
bot.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Integrations);
const project = await projectBotDAL.findProjectByBotId(botId);

View File

@@ -27,8 +27,22 @@ export const projectEnvServiceFactory = ({
projectDAL,
folderDAL
}: TProjectEnvServiceFactoryDep) => {
const createEnvironment = async ({ projectId, actorId, actor, actorOrgId, name, slug }: TCreateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const createEnvironment = async ({
projectId,
actorId,
actor,
actorOrgId,
actorAuthMethod,
name,
slug
}: TCreateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Environments);
const envs = await projectEnvDAL.find({ projectId });
@@ -65,11 +79,18 @@ export const projectEnvServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
name,
id,
position
}: TUpdateEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Environments);
const oldEnv = await projectEnvDAL.findOne({ id, projectId });
@@ -94,8 +115,14 @@ export const projectEnvServiceFactory = ({
return { environment: env, old: oldEnv };
};
const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgId, id }: TDeleteEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const deleteEnvironment = async ({ projectId, actor, actorId, actorOrgId, actorAuthMethod, id }: TDeleteEnvDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Environments);
const env = await projectEnvDAL.transaction(async (tx) => {

View File

@@ -26,11 +26,18 @@ export const projectKeyServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId,
nonce,
encryptedKey
}: TUploadProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
const receiverMembership = await projectMembershipDAL.findOne({
@@ -46,14 +53,32 @@ export const projectKeyServiceFactory = ({
await projectKeyDAL.create({ projectId, receiverId, encryptedKey, nonce, senderId: actorId });
};
const getLatestProjectKey = async ({ actorId, projectId, actor, actorOrgId }: TGetLatestProjectKeyDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const getLatestProjectKey = async ({
actorId,
projectId,
actor,
actorOrgId,
actorAuthMethod
}: TGetLatestProjectKeyDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId);
const latestKey = await projectKeyDAL.findLatestProjectKey(actorId, projectId);
return latestKey;
};
const getProjectPublicKeys = async ({ actor, actorId, actorOrgId, projectId }: TGetLatestProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const getProjectPublicKeys = async ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId
}: TGetLatestProjectKeyDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
return projectKeyDAL.findAllProjectUserPubKeys(projectId);
};

View File

@@ -67,8 +67,20 @@ export const projectMembershipServiceFactory = ({
projectKeyDAL,
licenseService
}: TProjectMembershipServiceFactoryDep) => {
const getProjectMemberships = async ({ actorId, actor, actorOrgId, projectId }: TGetProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const getProjectMemberships = async ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TGetProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Member);
return projectMembershipDAL.findAllProjectMembers(projectId);
@@ -79,13 +91,20 @@ export const projectMembershipServiceFactory = ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
members,
sendEmails = true
}: TAddUsersToWorkspaceDTO) => {
const project = await projectDAL.findById(projectId);
if (!project) throw new BadRequestError({ message: "Project not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member);
const orgMembers = await orgDAL.findMembership({
orgId: project.orgId,
@@ -145,6 +164,7 @@ export const projectMembershipServiceFactory = ({
const addUsersToProjectNonE2EE = async ({
projectId,
actorId,
actorAuthMethod,
actor,
emails,
usernames,
@@ -157,7 +177,7 @@ export const projectMembershipServiceFactory = ({
throw new BadRequestError({ message: "Please upgrade your project on your dashboard" });
}
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Member);
const usernamesAndEmails = [...emails, ...usernames];
@@ -273,11 +293,18 @@ export const projectMembershipServiceFactory = ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId,
membershipId,
roles
}: TUpdateProjectMembershipDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Member);
const membershipUser = await userDAL.findUserByProjectMembershipId(membershipId);
@@ -347,10 +374,17 @@ export const projectMembershipServiceFactory = ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId,
membershipId
}: TDeleteProjectMembershipOldDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
const member = await userDAL.findUserByProjectMembershipId(membershipId);
@@ -374,11 +408,18 @@ export const projectMembershipServiceFactory = ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId,
emails,
usernames
}: TDeleteProjectMembershipsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Member);
const project = await projectDAL.findById(projectId);

View File

@@ -13,7 +13,7 @@ import {
} from "@app/ee/services/permission/project-permission";
import { BadRequestError } from "@app/lib/errors";
import { ActorType } from "../auth/auth-type";
import { ActorAuthMethod, ActorType } from "../auth/auth-type";
import { TProjectRoleDALFactory } from "./project-role-dal";
type TProjectRoleServiceFactoryDep = {
@@ -29,9 +29,16 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actorId: string,
projectId: string,
data: Omit<TProjectRolesInsert, "projectId">,
actorAuthMethod: ActorAuthMethod,
actorOrgId?: string
) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Role);
const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId });
if (existingRole) throw new BadRequestError({ name: "Create Role", message: "Duplicate role" });
@@ -49,9 +56,16 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
projectId: string,
roleId: string,
data: Omit<TOrgRolesUpdate, "orgId">,
actorAuthMethod: ActorAuthMethod,
actorOrgId?: string
) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Role);
if (data?.slug) {
const existingRole = await projectRoleDAL.findOne({ slug: data.slug, projectId });
@@ -71,9 +85,16 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
actorId: string,
projectId: string,
roleId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId?: string
) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Role);
const [deletedRole] = await projectRoleDAL.delete({ id: roleId, projectId });
if (!deletedRole) throw new BadRequestError({ message: "Role not found", name: "Update role" });
@@ -81,8 +102,20 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return deletedRole;
};
const listRoles = async (actor: ActorType, actorId: string, projectId: string, actorOrgId?: string) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const listRoles = async (
actor: ActorType,
actorId: string,
projectId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId?: string
) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Role);
const customRoles = await projectRoleDAL.find({ projectId });
const roles = [
@@ -135,8 +168,18 @@ export const projectRoleServiceFactory = ({ projectRoleDAL, permissionService }:
return roles;
};
const getUserPermission = async (userId: string, projectId: string, actorOrgId?: string) => {
const { permission, membership } = await permissionService.getUserProjectPermission(userId, projectId, actorOrgId);
const getUserPermission = async (
userId: string,
projectId: string,
actorAuthMethod: ActorAuthMethod,
actorOrgId?: string
) => {
const { permission, membership } = await permissionService.getUserProjectPermission(
userId,
projectId,
actorAuthMethod,
actorOrgId
);
return { permissions: packRules(permission.rules), membership };
};

View File

@@ -96,6 +96,7 @@ export const projectServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
workspaceName,
slug: projectSlug
}: TCreateProjectDTO) => {
@@ -111,6 +112,7 @@ export const projectServiceFactory = ({
actor,
actorId,
organization.id,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Workspace);
@@ -330,10 +332,16 @@ export const projectServiceFactory = ({
return results;
};
const deleteProject = async ({ actor, actorId, actorOrgId, filter }: TDeleteProjectDTO) => {
const deleteProject = async ({ actor, actorId, actorOrgId, actorAuthMethod, filter }: TDeleteProjectDTO) => {
const project = await projectDAL.findProjectByFilter(filter);
const { permission } = await permissionService.getProjectPermission(actor, actorId, project.id, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
project.id,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project);
const deletedProject = await projectDAL.transaction(async (tx) => {
@@ -356,17 +364,23 @@ export const projectServiceFactory = ({
return workspaces;
};
const getAProject = async ({ actorId, actorOrgId, filter, actor }: TGetProjectDTO) => {
const getAProject = async ({ actorId, actorOrgId, actorAuthMethod, filter, actor }: TGetProjectDTO) => {
const project = await projectDAL.findProjectByFilter(filter);
await permissionService.getProjectPermission(actor, actorId, project.id, actorOrgId);
await permissionService.getProjectPermission(actor, actorId, project.id, actorAuthMethod, actorOrgId);
return project;
};
const updateProject = async ({ actor, actorId, actorOrgId, update, filter }: TUpdateProjectDTO) => {
const updateProject = async ({ actor, actorId, actorOrgId, actorAuthMethod, update, filter }: TUpdateProjectDTO) => {
const project = await projectDAL.findProjectByFilter(filter);
const { permission } = await permissionService.getProjectPermission(actor, actorId, project.id, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
project.id,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
const updatedProject = await projectDAL.updateById(project.id, {
@@ -381,25 +395,50 @@ export const projectServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
autoCapitalization
}: TToggleProjectAutoCapitalizationDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
const updatedProject = await projectDAL.updateById(projectId, { autoCapitalization });
return updatedProject;
};
const updateName = async ({ projectId, actor, actorId, actorOrgId, name }: TUpdateProjectNameDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const updateName = async ({
projectId,
actor,
actorId,
actorOrgId,
actorAuthMethod,
name
}: TUpdateProjectNameDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
const updatedProject = await projectDAL.updateById(projectId, { name });
return updatedProject;
};
const upgradeProject = async ({ projectId, actor, actorId, userPrivateKey }: TUpgradeProjectDTO) => {
const { permission, hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId);
const upgradeProject = async ({ projectId, actor, actorId, actorAuthMethod, userPrivateKey }: TUpgradeProjectDTO) => {
const { permission, hasRole } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Project);
@@ -423,8 +462,8 @@ export const projectServiceFactory = ({
});
};
const getProjectUpgradeStatus = async ({ projectId, actor, actorId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
const getProjectUpgradeStatus = async ({ projectId, actor, actorAuthMethod, actorId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Secrets);
const project = await projectDAL.findProjectById(projectId);

View File

@@ -28,16 +28,17 @@ export const secretBlindIndexServiceFactory = ({
actor,
projectId,
actorId,
actorAuthMethod,
actorOrgId
}: TGetProjectBlindIndexStatusDTO) => {
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId);
const secretCount = await secretBlindIndexDAL.countOfSecretsWithNullSecretBlindIndex(projectId);
return Number(secretCount);
};
const getProjectSecrets = async ({ projectId, actorId, actor }: TGetProjectSecretsDTO) => {
const { hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId);
const getProjectSecrets = async ({ projectId, actorId, actorAuthMethod, actor }: TGetProjectSecretsDTO) => {
const { hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod);
if (!hasRole(ProjectMembershipRole.Admin)) {
throw new UnauthorizedError({ message: "User must be admin" });
}
@@ -50,10 +51,17 @@ export const secretBlindIndexServiceFactory = ({
projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId,
secretsToUpdate
}: TUpdateProjectSecretNameDTO) => {
const { hasRole } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { hasRole } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
if (!hasRole(ProjectMembershipRole.Admin)) {
throw new UnauthorizedError({ message: "User must be admin" });
}

View File

@@ -34,12 +34,19 @@ export const secretFolderServiceFactory = ({
projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId,
name,
environment,
path: secretPath
}: TCreateFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@@ -114,12 +121,19 @@ export const secretFolderServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
name,
environment,
path: secretPath,
id
}: TUpdateFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@@ -162,11 +176,18 @@ export const secretFolderServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
environment,
path: secretPath,
idOrName
}: TDeleteFolderDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
@@ -196,12 +217,13 @@ export const secretFolderServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
environment,
path: secretPath
}: TGetFolderDTO) => {
// folder list is allowed to be read by anyone
// permission to check does user has access
await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
await permissionService.getProjectPermission(actor, actorId, projectId, actorAuthMethod, actorOrgId);
const env = await projectEnvDAL.findOne({ projectId, slug: environment });
if (!env) throw new BadRequestError({ message: "Environment not found", name: "get folders" });

View File

@@ -45,10 +45,17 @@ export const secretImportServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId,
path
}: TCreateSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
// check if user has permission to import into destination path
ForbiddenError.from(permission).throwUnlessCan(
@@ -97,10 +104,17 @@ export const secretImportServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
data,
id
}: TUpdateSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -144,9 +158,16 @@ export const secretImportServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
id
}: TDeleteSecretImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -167,8 +188,22 @@ export const secretImportServiceFactory = ({
return secImport;
};
const getImports = async ({ path, environment, projectId, actor, actorId, actorOrgId }: TGetSecretImportsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const getImports = async ({
path,
environment,
projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TGetSecretImportsDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -186,10 +221,17 @@ export const secretImportServiceFactory = ({
environment,
projectId,
actor,
actorAuthMethod,
actorId,
actorOrgId
}: TGetSecretsFromImportDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })

View File

@@ -15,8 +15,23 @@ type TSecretTagServiceFactoryDep = {
export type TSecretTagServiceFactory = ReturnType<typeof secretTagServiceFactory>;
export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSecretTagServiceFactoryDep) => {
const createTag = async ({ name, slug, actor, color, actorId, actorOrgId, projectId }: TCreateTagDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const createTag = async ({
name,
slug,
actor,
color,
actorId,
actorOrgId,
actorAuthMethod,
projectId
}: TCreateTagDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Tags);
const existingTag = await secretTagDAL.findOne({ slug, projectId });
@@ -32,19 +47,31 @@ export const secretTagServiceFactory = ({ secretTagDAL, permissionService }: TSe
return newTag;
};
const deleteTag = async ({ actorId, actor, actorOrgId, id }: TDeleteTagDTO) => {
const deleteTag = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteTagDTO) => {
const tag = await secretTagDAL.findById(id);
if (!tag) throw new BadRequestError({ message: "Tag doesn't exist" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, tag.projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
tag.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Tags);
const deletedTag = await secretTagDAL.deleteById(tag.id);
return deletedTag;
};
const getProjectTags = async ({ actor, actorId, actorOrgId, projectId }: TListProjectTagsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const getProjectTags = async ({ actor, actorId, actorOrgId, actorAuthMethod, projectId }: TListProjectTagsDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Tags);
const tags = await secretTagDAL.find({ projectId }, { sort: [["createdAt", "asc"]] });

View File

@@ -145,10 +145,17 @@ export const secretServiceFactory = ({
actorId,
actorOrgId,
environment,
actorAuthMethod,
projectId,
...inputSecret
}: TCreateSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -230,10 +237,17 @@ export const secretServiceFactory = ({
actorId,
actorOrgId,
environment,
actorAuthMethod,
projectId,
...inputSecret
}: TUpdateSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -341,11 +355,18 @@ export const secretServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
environment,
projectId,
...inputSecret
}: TDeleteSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -401,9 +422,16 @@ export const secretServiceFactory = ({
projectId,
actor,
actorOrgId,
actorAuthMethod,
includeImports
}: TGetSecretsDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -445,6 +473,7 @@ export const secretServiceFactory = ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId,
environment,
path,
@@ -453,7 +482,13 @@ export const secretServiceFactory = ({
version,
includeImports
}: TGetASecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -534,12 +569,19 @@ export const secretServiceFactory = ({
path,
actor,
actorId,
actorAuthMethod,
actorOrgId,
environment,
projectId,
secrets: inputSecrets
}: TCreateBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -597,11 +639,18 @@ export const secretServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
environment,
projectId,
secrets: inputSecrets
}: TUpdateBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -678,9 +727,16 @@ export const secretServiceFactory = ({
projectId,
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TDeleteBulkSecretDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
@@ -728,6 +784,7 @@ export const secretServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
environment,
includeImports
}: TGetSecretsRawDTO) => {
@@ -740,6 +797,7 @@ export const secretServiceFactory = ({
environment,
actor,
actorOrgId,
actorAuthMethod,
path,
includeImports
});
@@ -763,6 +821,7 @@ export const secretServiceFactory = ({
projectId,
actorId,
actorOrgId,
actorAuthMethod,
secretName,
includeImports,
version
@@ -773,6 +832,7 @@ export const secretServiceFactory = ({
const secret = await getSecretByName({
actorId,
projectId,
actorAuthMethod,
environment,
actor,
actorOrgId,
@@ -792,6 +852,7 @@ export const secretServiceFactory = ({
environment,
actor,
actorOrgId,
actorAuthMethod,
type,
secretPath,
secretValue,
@@ -813,6 +874,7 @@ export const secretServiceFactory = ({
path: secretPath,
actor,
actorId,
actorAuthMethod,
actorOrgId,
secretKeyCiphertext: secretKeyEncrypted.ciphertext,
secretKeyIV: secretKeyEncrypted.iv,
@@ -839,6 +901,7 @@ export const secretServiceFactory = ({
environment,
actor,
actorOrgId,
actorAuthMethod,
type,
secretPath,
secretValue,
@@ -858,6 +921,7 @@ export const secretServiceFactory = ({
actor,
actorId,
actorOrgId,
actorAuthMethod,
secretValueCiphertext: secretValueEncrypted.ciphertext,
secretValueIV: secretValueEncrypted.iv,
secretValueTag: secretValueEncrypted.tag,
@@ -877,6 +941,7 @@ export const secretServiceFactory = ({
environment,
actor,
actorOrgId,
actorAuthMethod,
type,
secretPath
}: TDeleteSecretRawDTO) => {
@@ -891,7 +956,8 @@ export const secretServiceFactory = ({
path: secretPath,
actor,
actorId,
actorOrgId
actorOrgId,
actorAuthMethod
});
await snapshotService.performSnapshot(secret.folderId);
@@ -904,6 +970,7 @@ export const secretServiceFactory = ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
limit = 20,
offset = 0,
secretId
@@ -914,7 +981,13 @@ export const secretServiceFactory = ({
const folder = await folderDAL.findById(secret.folderId);
if (!folder) throw new BadRequestError({ message: "Failed to find secret" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, folder.projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
folder.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });

View File

@@ -43,6 +43,7 @@ export const serviceTokenServiceFactory = ({
name,
actor,
actorOrgId,
actorAuthMethod,
scopes,
actorId,
projectId,
@@ -50,7 +51,13 @@ export const serviceTokenServiceFactory = ({
permissions,
encryptedKey
}: TCreateServiceTokenDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.ServiceTokens);
scopes.forEach(({ environment, secretPath }) => {
@@ -94,7 +101,7 @@ export const serviceTokenServiceFactory = ({
return { token, serviceToken };
};
const deleteServiceToken = async ({ actorId, actor, actorOrgId, id }: TDeleteServiceTokenDTO) => {
const deleteServiceToken = async ({ actorId, actor, actorOrgId, actorAuthMethod, id }: TDeleteServiceTokenDTO) => {
const serviceToken = await serviceTokenDAL.findById(id);
if (!serviceToken) throw new BadRequestError({ message: "Token not found" });
@@ -102,6 +109,7 @@ export const serviceTokenServiceFactory = ({
actor,
actorId,
serviceToken.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.ServiceTokens);
@@ -122,8 +130,20 @@ export const serviceTokenServiceFactory = ({
return { serviceToken, user: serviceTokenUser };
};
const getProjectServiceTokens = async ({ actorId, actor, actorOrgId, projectId }: TProjectServiceTokensDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const getProjectServiceTokens = async ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId
}: TProjectServiceTokensDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.ServiceTokens);
const tokens = await serviceTokenDAL.find({ projectId }, { sort: [["createdAt", "desc"]] });

View File

@@ -136,6 +136,7 @@ export const superAdminServiceFactory = ({
await updateServerCfg({ initialized: true });
const token = await authService.generateUserTokens({
user: userInfo.user,
authMethod: AuthMethod.EMAIL,
ip,
userAgent,
organizationId: undefined

View File

@@ -31,13 +31,20 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
actor,
actorId,
actorOrgId,
actorAuthMethod,
projectId,
webhookUrl,
environment,
secretPath,
webhookSecretKey
}: TCreateWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Webhooks);
const env = await projectEnvDAL.findOne({ projectId, slug: environment });
if (!env) throw new BadRequestError({ message: "Env not found" });
@@ -73,33 +80,51 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
return { ...webhook, projectId, environment: env };
};
const updateWebhook = async ({ actorId, actor, actorOrgId, id, isDisabled }: TUpdateWebhookDTO) => {
const updateWebhook = async ({ actorId, actor, actorOrgId, actorAuthMethod, id, isDisabled }: TUpdateWebhookDTO) => {
const webhook = await webhookDAL.findById(id);
if (!webhook) throw new BadRequestError({ message: "Webhook not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
webhook.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Webhooks);
const updatedWebhook = await webhookDAL.updateById(id, { isDisabled });
return { ...webhook, ...updatedWebhook };
};
const deleteWebhook = async ({ id, actor, actorId, actorOrgId }: TDeleteWebhookDTO) => {
const deleteWebhook = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TDeleteWebhookDTO) => {
const webhook = await webhookDAL.findById(id);
if (!webhook) throw new BadRequestError({ message: "Webhook not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
webhook.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Webhooks);
const deletedWebhook = await webhookDAL.deleteById(id);
return { ...webhook, ...deletedWebhook };
};
const testWebhook = async ({ id, actor, actorId, actorOrgId }: TTestWebhookDTO) => {
const testWebhook = async ({ id, actor, actorId, actorAuthMethod, actorOrgId }: TTestWebhookDTO) => {
const webhook = await webhookDAL.findById(id);
if (!webhook) throw new BadRequestError({ message: "Webhook not found" });
const { permission } = await permissionService.getProjectPermission(actor, actorId, webhook.projectId, actorOrgId);
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
webhook.projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
let webhookError: string | undefined;
@@ -119,8 +144,22 @@ export const webhookServiceFactory = ({ webhookDAL, projectEnvDAL, permissionSer
return { ...webhook, ...updatedWebhook };
};
const listWebhooks = async ({ actorId, actor, actorOrgId, projectId, secretPath, environment }: TListWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
const listWebhooks = async ({
actorId,
actor,
actorOrgId,
actorAuthMethod,
projectId,
secretPath,
environment
}: TListWebhookDTO) => {
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Webhooks);
return webhookDAL.findAllWebhooks(projectId, environment, secretPath);