Canvas: Implement authorization
Run internal API server on a different port: DODO_PORT_API
Change-Id: Ic5aa066c3fa06bd68a752704df4f73040d1aa0d0
diff --git a/apps/canvas/back/package-lock.json b/apps/canvas/back/package-lock.json
index c6fa655..b327134 100644
--- a/apps/canvas/back/package-lock.json
+++ b/apps/canvas/back/package-lock.json
@@ -23,7 +23,7 @@
"eslint": "^9.13.0",
"prettier": "3.5.3",
"prisma": "^6.6.0",
- "typescript": "^5.6.3",
+ "typescript": "^5.8.3",
"typescript-eslint": "^8.11.0"
}
},
@@ -4722,10 +4722,11 @@
}
},
"node_modules/typescript": {
- "version": "5.6.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
- "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
+ "version": "5.8.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
+ "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"devOptional": true,
+ "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/apps/canvas/back/package.json b/apps/canvas/back/package.json
index 16bc055..2c9c432 100644
--- a/apps/canvas/back/package.json
+++ b/apps/canvas/back/package.json
@@ -28,7 +28,7 @@
"eslint": "^9.13.0",
"prettier": "3.5.3",
"prisma": "^6.6.0",
- "typescript": "^5.6.3",
+ "typescript": "^5.8.3",
"typescript-eslint": "^8.11.0"
},
"prettier": {
@@ -41,4 +41,4 @@
"bracketSpacing": true,
"arrowParens": "always"
}
-}
\ No newline at end of file
+}
diff --git a/apps/canvas/back/src/index.ts b/apps/canvas/back/src/index.ts
index d5c1b2d..653eeaa 100644
--- a/apps/canvas/back/src/index.ts
+++ b/apps/canvas/back/src/index.ts
@@ -15,7 +15,7 @@
try {
const { id } = await db.project.create({
data: {
- userId: "gio", // req.get("x-forwarded-userid")!,
+ userId: resp.locals.userId,
name: req.body.name,
},
});
@@ -38,7 +38,7 @@
try {
const r = await db.project.findMany({
where: {
- userId: "gio", // req.get("x-forwarded-userid")!,
+ userId: resp.locals.userId,
},
});
resp.status(200);
@@ -64,6 +64,7 @@
await db.project.update({
where: {
id: Number(req.params["projectId"]),
+ userId: resp.locals.userId,
},
data: {
draft: Buffer.from(JSON.stringify(req.body)),
@@ -83,6 +84,7 @@
const r = await db.project.findUnique({
where: {
id: Number(req.params["projectId"]),
+ userId: resp.locals.userId,
},
select: {
state: true,
@@ -122,6 +124,7 @@
const p = await db.project.findUnique({
where: {
id: projectId,
+ userId: resp.locals.userId,
},
select: {
instanceId: true,
@@ -158,6 +161,7 @@
const p = await db.project.findUnique({
where: {
id: projectId,
+ userId: resp.locals.userId,
},
select: {
instanceId: true,
@@ -186,7 +190,6 @@
config: req.body.config,
},
});
- console.log(r);
if (r.status === 200) {
await db.project.update({
where: {
@@ -254,12 +257,12 @@
const p = await db.project.findUnique({
where: {
id: projectId,
+ userId: resp.locals.userId,
},
select: {
instanceId: true,
},
});
- console.log(projectId, p);
if (p === null) {
resp.status(404);
return;
@@ -288,8 +291,13 @@
try {
const projectId = Number(req.params["projectId"]);
const project = await db.project.findUnique({
- where: { id: projectId },
- select: { githubToken: true },
+ where: {
+ id: projectId,
+ userId: resp.locals.userId,
+ },
+ select: {
+ githubToken: true,
+ },
});
if (!project?.githubToken) {
@@ -319,7 +327,10 @@
const { githubToken } = req.body;
await db.project.update({
- where: { id: projectId },
+ where: {
+ id: projectId,
+ userId: resp.locals.userId,
+ },
data: { githubToken },
});
@@ -336,7 +347,10 @@
const projectId = Number(req.params["projectId"]);
try {
const project = await db.project.findUnique({
- where: { id: projectId },
+ where: {
+ id: projectId,
+ userId: resp.locals.userId,
+ },
select: {
deployKey: true,
githubToken: true,
@@ -356,7 +370,7 @@
resp.write(
JSON.stringify({
// TODO(gio): get from env or command line flags
- managerAddr: "http://10.42.0.239:8080",
+ managerAddr: "http://10.42.0.211:8081",
deployKey: project.deployKey,
integrations: {
github: !!project.githubToken,
@@ -387,6 +401,17 @@
try {
const projectId = Number(req.params["projectId"]);
const service = req.params["service"];
+ const project = await db.project.findUnique({
+ where: {
+ id: projectId,
+ userId: resp.locals.userId,
+ },
+ });
+ if (project == null) {
+ resp.status(404);
+ resp.write(JSON.stringify({ error: "Project not found" }));
+ return;
+ }
const projectLogs = logs.get(projectId);
if (!projectLogs) {
@@ -435,7 +460,6 @@
return;
}
- console.log(result);
const { service, address, logs: log } = result.data;
// Get existing workers or initialize empty array
@@ -471,6 +495,17 @@
try {
const projectId = Number(req.params["projectId"]);
const projectWorkers = workers.get(projectId) || [];
+ const project = await db.project.findUnique({
+ where: {
+ id: projectId,
+ userId: resp.locals.userId,
+ },
+ });
+ if (project == null) {
+ resp.status(404);
+ resp.write(JSON.stringify({ error: "Project not found" }));
+ return;
+ }
if (projectWorkers.length === 0) {
resp.status(404);
@@ -501,10 +536,23 @@
}
};
+const auth = (req: express.Request, resp: express.Response, next: express.NextFunction) => {
+ const userId = req.get("x-forwarded-userid");
+ if (userId === undefined) {
+ resp.status(401);
+ resp.write("Unauthorized");
+ resp.end();
+ return;
+ }
+ resp.locals.userId = userId;
+ next();
+};
+
async function start() {
await db.$connect();
const app = express();
app.use(express.json());
+ app.use(auth);
app.post("/api/project/:projectId/saved", handleSave);
app.get("/api/project/:projectId/saved", handleSavedGet);
app.post("/api/project/:projectId/deploy", handleDeploy);
@@ -515,12 +563,21 @@
app.get("/api/project/:projectId/repos/github", handleGithubRepos);
app.post("/api/project/:projectId/github-token", handleUpdateGithubToken);
app.get("/api/project/:projectId/env", handleEnv);
- app.post("/api/project/:projectId/workers", handleRegisterWorker);
app.post("/api/project/:projectId/reload", handleReload);
app.get("/api/project/:projectId/logs/:service", handleServiceLogs);
app.use("/", express.static("../front/dist"));
+
+ const api = express();
+ api.use(express.json());
+ api.post("/api/project/:projectId/workers", handleRegisterWorker);
+
+ // Start both servers
app.listen(env.DODO_PORT_WEB, () => {
- console.log("started");
+ console.log("Web server started on port", env.DODO_PORT_WEB);
+ });
+
+ api.listen(env.DODO_PORT_API, () => {
+ console.log("Internal API server started on port", env.DODO_PORT_API);
});
}
diff --git a/apps/canvas/front/src/lib/state.ts b/apps/canvas/front/src/lib/state.ts
index 428ae17..21dbbc4 100644
--- a/apps/canvas/front/src/lib/state.ts
+++ b/apps/canvas/front/src/lib/state.ts
@@ -315,7 +315,7 @@
export const envSchema = z.object({
managerAddr: z.optional(z.string().min(1)),
- deployKey: z.optional(z.string().min(1)),
+ deployKey: z.optional(z.nullable(z.string().min(1))),
networks: z
.array(
z.object({