Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API environment endpoints #2529

Merged
merged 15 commits into from
May 30, 2024
169 changes: 169 additions & 0 deletions packages/back-end/generated/spec.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion packages/back-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
"generate-api-types": "yarn generate-api-models && swagger-cli bundle -t yaml src/api/openapi/openapi.tmp.yaml -o generated/spec.yaml && node src/scripts/generate-openapi.mjs"
},
"dependencies": {
"@aws-sdk/client-sts": "^3.567.0",
"@aws-sdk/client-athena": "^3.564.0",
"@aws-sdk/client-sts": "^3.567.0",
"@clickhouse/client": "^1.0.1",
"@databricks/sql": "^1.8.1",
"@dqbd/tiktoken": "^1.0.7",
Expand Down Expand Up @@ -141,7 +141,9 @@
"delay-cli": "^2.0.0",
"jest": "^27.1.1",
"minimist": "^1.2.8",
"mongodb-memory-server": "^9.2.0",
"rimraf": "^3.0.2",
"supertest": "^7.0.0",
"typescript": "5.3.3"
},
"optionalDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions packages/back-end/src/api/api.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import experimentsRouter from "./experiments/experiments.router";
import metricsRouter from "./metrics/metrics.router";
import segmentsRouter from "./segments/segments.router";
import projectsRouter from "./projects/projects.router";
import environmentsRouter from "./environments/environments.router";
import savedGroupsRouter from "./saved-groups/saved-groups.router";
import sdkConnectionsRouter from "./sdk-connections/sdk-connections.router";
import sdkPayloadRouter from "./sdk-payload/sdk-payload.router";
Expand Down Expand Up @@ -82,6 +83,7 @@ router.use("/metrics", metricsRouter);
router.use("/segments", segmentsRouter);
router.use("/dimensions", dimensionsRouter);
router.use("/projects", projectsRouter);
router.use("/environments", environmentsRouter);
router.use("/sdk-connections", sdkConnectionsRouter);
router.use("/data-sources", dataSourcesRouter);
router.use("/visual-changesets", visualChangesetsRouter);
Expand Down
46 changes: 46 additions & 0 deletions packages/back-end/src/api/environments/deleteEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { DeleteEnvironmentResponse } from "../../../types/openapi";
import { createApiRequestHandler } from "../../util/handler";
import { deleteEnvironmentValidator } from "../../validators/openapi";
import { updateOrganization } from "../../models/OrganizationModel";
import { OrganizationInterface } from "../../../types/organization";
import { auditDetailsDelete } from "../../services/audit";

export const deleteEnvironment = createApiRequestHandler(
deleteEnvironmentValidator
)(
async (req): Promise<DeleteEnvironmentResponse> => {
const id = req.params.id;
const org = req.context.org;
const environments = org.settings?.environments || [];

const environment = environments.find((env) => env.id === id);
if (!environment) {
throw Error(`Environment ${id} does not exists!`);
}

if (!req.context.permissions.canDeleteEnvironment(environment))
req.context.permissions.throwPermissionError();

const updates: Partial<OrganizationInterface> = {
settings: {
...org.settings,
environments: [...environments.filter((env) => env.id !== id)],
},
};

await updateOrganization(org.id, updates);

await req.audit({
event: "environment.delete",
entity: {
object: "environment",
id: environment.id,
},
details: auditDetailsDelete(environment),
});

return {
deletedId: id,
};
}
);
14 changes: 14 additions & 0 deletions packages/back-end/src/api/environments/environments.router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Router } from "express";
import { listEnvironments } from "./listEnvironments";
import { putEnvironment } from "./putEnvironment";
import { postEnvironment } from "./postEnvironment";
import { deleteEnvironment } from "./deleteEnvironment";

const router = Router();

router.get("/", listEnvironments);
router.post("/", postEnvironment);
router.put("/:id", putEnvironment);
router.delete("/:id", deleteEnvironment);

export default router;
33 changes: 33 additions & 0 deletions packages/back-end/src/api/environments/listEnvironments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ListEnvironmentsResponse } from "../../../types/openapi";
import { createApiRequestHandler } from "../../util/handler";
import { listEnvironmentsValidator } from "../../validators/openapi";

export const listEnvironments = createApiRequestHandler(
listEnvironmentsValidator
)(
async (req): Promise<ListEnvironmentsResponse> => {
const environments = (
req.context.org.settings?.environments || []
).filter((environment) =>
req.context.permissions.canReadMultiProjectResource(environment.projects)
);

return {
environments: environments.map(
({
id,
description = "",
toggleOnList = false,
defaultState = false,
projects = [],
}) => ({
id,
projects,
description,
defaultState,
toggleOnList,
})
),
};
}
);
46 changes: 46 additions & 0 deletions packages/back-end/src/api/environments/postEnvironment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { PostEnvironmentResponse } from "../../../types/openapi";
import { createApiRequestHandler } from "../../util/handler";
import { postEnvironmentValidator } from "../../validators/openapi";
import { updateOrganization } from "../../models/OrganizationModel";
import { OrganizationInterface } from "../../../types/organization";
import { auditDetailsCreate } from "../../services/audit";
import { validatePayload } from "./validations";

export const postEnvironment = createApiRequestHandler(
postEnvironmentValidator
)(
async (req): Promise<PostEnvironmentResponse> => {
const environment = await validatePayload(req.context, req.body);

const org = req.context.org;

if (org.settings?.environments?.some((env) => env.id === environment.id)) {
throw Error(`Environment ${environment.id} already exists!`);
}

if (!req.context.permissions.canCreateOrUpdateEnvironment(environment))
req.context.permissions.throwPermissionError();

const updates: Partial<OrganizationInterface> = {
settings: {
...org.settings,
environments: [...(org.settings?.environments || []), environment],
},
};

await updateOrganization(org.id, updates);

await req.audit({
event: "environment.create",
entity: {
object: "environment",
id: environment.id,
},
details: auditDetailsCreate(environment),
});

return {
environment,
};
}
);
Loading
Loading