Canvas: Implement authorization

Run internal API server on a different port: DODO_PORT_API

Change-Id: Ic5aa066c3fa06bd68a752704df4f73040d1aa0d0
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);
 	});
 }