mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 16:40:30 +00:00
feat: changed backend-pg to backend
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify } from "@app/lib/knex";
|
||||
|
||||
export type TProjectEnvDALFactory = ReturnType<typeof projectEnvDALFactory>;
|
||||
|
||||
export const projectEnvDALFactory = (db: TDbClient) => {
|
||||
const projectEnvOrm = ormify(db, TableName.Environment);
|
||||
|
||||
const findBySlugs = async (projectId: string, env: string[], tx?: Knex) => {
|
||||
try {
|
||||
const envs = await (tx || db)(TableName.Environment)
|
||||
.where("projectId", projectId)
|
||||
.whereIn("slug", env);
|
||||
return envs;
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "Find by slugs" });
|
||||
}
|
||||
};
|
||||
|
||||
// we are using postion based sorting as its a small list
|
||||
// this will return the last value of the position in a folder with secret imports
|
||||
const findLastEnvPosition = async (projectId: string, tx?: Knex) => {
|
||||
const lastPos = await (tx || db)(TableName.Environment)
|
||||
.where({ projectId })
|
||||
.max({ position: "position" })
|
||||
.first();
|
||||
return lastPos?.position || 0;
|
||||
};
|
||||
|
||||
const updateAllPosition = async (
|
||||
projectId: string,
|
||||
pos: number,
|
||||
targetPos: number,
|
||||
tx?: Knex
|
||||
) => {
|
||||
try {
|
||||
if (targetPos === -1) {
|
||||
// this means delete
|
||||
await (tx || db)(TableName.Environment)
|
||||
.where({ projectId })
|
||||
.andWhere("position", ">", pos)
|
||||
.decrement("position", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetPos > pos) {
|
||||
await (tx || db)(TableName.Environment)
|
||||
.where({ projectId })
|
||||
.where("position", "<=", targetPos)
|
||||
.andWhere("position", ">", pos)
|
||||
.decrement("position", 1);
|
||||
} else {
|
||||
await (tx || db)(TableName.Environment)
|
||||
.where({ projectId })
|
||||
.where("position", ">=", targetPos)
|
||||
.andWhere("position", "<", pos)
|
||||
.increment("position", 1);
|
||||
}
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "UpdateEnvPos" });
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
...projectEnvOrm,
|
||||
findBySlugs,
|
||||
findLastEnvPosition,
|
||||
updateAllPosition
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,131 @@
|
||||
import { ForbiddenError } from "@casl/ability";
|
||||
|
||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/ee/services/permission/project-permission";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TProjectEnvDALFactory } from "./project-env-dal";
|
||||
import { TCreateEnvDTO, TDeleteEnvDTO, TUpdateEnvDTO } from "./project-env-types";
|
||||
|
||||
type TProjectEnvServiceFactoryDep = {
|
||||
projectEnvDAL: TProjectEnvDALFactory;
|
||||
folderDAL: Pick<TSecretFolderDALFactory, "create">;
|
||||
projectDAL: Pick<TProjectDALFactory, "findById">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||
};
|
||||
|
||||
export type TProjectEnvServiceFactory = ReturnType<typeof projectEnvServiceFactory>;
|
||||
|
||||
export const projectEnvServiceFactory = ({
|
||||
projectEnvDAL,
|
||||
permissionService,
|
||||
licenseService,
|
||||
projectDAL,
|
||||
folderDAL
|
||||
}: TProjectEnvServiceFactoryDep) => {
|
||||
const createEnvironment = async ({ projectId, actorId, actor, name, slug }: TCreateEnvDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Create,
|
||||
ProjectPermissionSub.Environments
|
||||
);
|
||||
|
||||
const envs = await projectEnvDAL.find({ projectId });
|
||||
const existingEnv = envs.find(({ slug: envSlug }) => envSlug === slug);
|
||||
if (existingEnv)
|
||||
throw new BadRequestError({
|
||||
message: "Environment with slug already exist",
|
||||
name: "Create envv"
|
||||
});
|
||||
|
||||
const project = await projectDAL.findById(projectId);
|
||||
const plan = await licenseService.getPlan(project.orgId);
|
||||
if (plan.environmentLimit !== null && envs.length >= plan.environmentLimit) {
|
||||
// case: limit imposed on number of environments allowed
|
||||
// case: number of environments used exceeds the number of environments allowed
|
||||
throw new BadRequestError({
|
||||
message:
|
||||
"Failed to create environment due to environment limit reached. Upgrade plan to create more environments."
|
||||
});
|
||||
}
|
||||
|
||||
const env = await projectEnvDAL.transaction(async (tx) => {
|
||||
const lastPos = await projectEnvDAL.findLastEnvPosition(projectId, tx);
|
||||
const doc = await projectEnvDAL.create({ slug, name, projectId, position: lastPos + 1 }, tx);
|
||||
await folderDAL.create({ name: "root", parentId: null, envId: doc.id, version: 1 }, tx);
|
||||
return doc;
|
||||
});
|
||||
return env;
|
||||
};
|
||||
|
||||
const updateEnvironment = async ({
|
||||
projectId,
|
||||
slug,
|
||||
actor,
|
||||
actorId,
|
||||
name,
|
||||
id,
|
||||
position
|
||||
}: TUpdateEnvDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionSub.Environments
|
||||
);
|
||||
|
||||
const oldEnv = await projectEnvDAL.findOne({ id, projectId });
|
||||
if (!oldEnv) throw new BadRequestError({ message: "Environment not found" });
|
||||
|
||||
if (slug) {
|
||||
const existingEnv = await projectEnvDAL.findOne({ slug });
|
||||
if (existingEnv && existingEnv.id !== id) {
|
||||
throw new BadRequestError({
|
||||
message: "Environment with slug already exist",
|
||||
name: "Create envv"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const env = await projectEnvDAL.transaction(async (tx) => {
|
||||
if (position) {
|
||||
await projectEnvDAL.updateAllPosition(projectId, oldEnv.position, position, tx);
|
||||
}
|
||||
return projectEnvDAL.updateById(oldEnv.id, { name, slug, position }, tx);
|
||||
});
|
||||
return { environment: env, old: oldEnv };
|
||||
};
|
||||
|
||||
const deleteEnvironment = async ({ projectId, actor, actorId, id }: TDeleteEnvDTO) => {
|
||||
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Delete,
|
||||
ProjectPermissionSub.Environments
|
||||
);
|
||||
|
||||
const env = await projectEnvDAL.transaction(async (tx) => {
|
||||
const [doc] = await projectEnvDAL.delete({ id, projectId }, tx);
|
||||
if (!doc)
|
||||
throw new BadRequestError({
|
||||
message: "Env doesn't exist",
|
||||
name: "Re-order env"
|
||||
});
|
||||
|
||||
await projectEnvDAL.updateAllPosition(projectId, doc.position, -1, tx);
|
||||
return doc;
|
||||
});
|
||||
return env;
|
||||
};
|
||||
|
||||
return {
|
||||
createEnvironment,
|
||||
updateEnvironment,
|
||||
deleteEnvironment
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import { TProjectPermission } from "@app/lib/types";
|
||||
|
||||
export type TCreateEnvDTO = {
|
||||
name: string;
|
||||
slug: string;
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TUpdateEnvDTO = {
|
||||
id: string;
|
||||
name?: string;
|
||||
slug?: string;
|
||||
position?: number;
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TDeleteEnvDTO = {
|
||||
id: string;
|
||||
} & TProjectPermission;
|
||||
|
||||
export type TReorderEnvDTO = {
|
||||
id: string;
|
||||
pos: number;
|
||||
} & TProjectPermission;
|
||||
Reference in New Issue
Block a user