feat: initial scaffold - backend, frontend, Prisma schema, Docker
- Prisma schema: User, Session, RepoConfig, Preview, Job, WebhookToken, NoConfigComment, AdminSettings - Backend: auth (login/logout/me/first-user setup), webhook handler with HMAC verification, EC2 service, SSH service, deploy pipeline, job queue worker, cron workers - Frontend: Login with first-user detection, Dashboard, PreviewDetail with live log streaming, Settings, Repos config, Admin panel, SetupWizard, Privacy page - Docker Compose and Dockerfile for self-hosted deployment - Uses bcryptjs for Node 24 compatibility Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var auth_exports = {};
|
||||
__export(auth_exports, {
|
||||
COOKIE_NAME_EXPORT: () => COOKIE_NAME_EXPORT,
|
||||
authEnforcementMiddleware: () => authEnforcementMiddleware,
|
||||
authResolutionMiddleware: () => authResolutionMiddleware
|
||||
});
|
||||
module.exports = __toCommonJS(auth_exports);
|
||||
var import_rjweb_server = require("rjweb-server");
|
||||
var import_db = require("../db");
|
||||
var import_logger = require("../logger");
|
||||
var import_errors = require("../errors");
|
||||
const log = (0, import_logger.createLogger)("AUTH");
|
||||
const COOKIE_NAME = "pp_session";
|
||||
const authResolutionMiddleware = new import_rjweb_server.Middleware(
|
||||
"Auth Resolution Middleware",
|
||||
"1.0.0"
|
||||
).load(() => {
|
||||
log.info("Auth resolution middleware loaded");
|
||||
}).httpRequest(async (_config, _server, context, ctr) => {
|
||||
const cookieToken = ctr.cookies.get(COOKIE_NAME);
|
||||
const tokenProvided = Boolean(cookieToken);
|
||||
const data = context.data(authResolutionMiddleware);
|
||||
if (!cookieToken) {
|
||||
data.auth = { success: false, message: "No session", tokenProvided: false };
|
||||
return;
|
||||
}
|
||||
const session = await import_db.prisma.session.findFirst({
|
||||
where: { hash: cookieToken },
|
||||
include: { user: true }
|
||||
});
|
||||
if (!session) {
|
||||
data.auth = { success: false, message: "Invalid session", tokenProvided };
|
||||
return;
|
||||
}
|
||||
data.auth = { success: true, user: session.user, sessionId: session.id };
|
||||
}).httpRequestContext(
|
||||
(_config, Original) => class extends Original {
|
||||
getAuth() {
|
||||
const data = this.context.data(authResolutionMiddleware);
|
||||
if (!data.auth) {
|
||||
return { success: false, message: "Auth not resolved", tokenProvided: false };
|
||||
}
|
||||
return data.auth;
|
||||
}
|
||||
}
|
||||
).export();
|
||||
const authEnforcementMiddleware = new import_rjweb_server.Middleware(
|
||||
"Auth Enforcement Middleware",
|
||||
"1.0.0"
|
||||
).httpRequest(async (_config, _server, context, ctr, end) => {
|
||||
const data = context.data(authResolutionMiddleware);
|
||||
const auth = data.auth;
|
||||
if (!auth || auth.success || !auth.tokenProvided) {
|
||||
return;
|
||||
}
|
||||
return end(
|
||||
ctr.status(import_errors.ERROR_MESSAGES.UNAUTHORIZED.code).print({
|
||||
status: "FAILED",
|
||||
message: auth.message
|
||||
})
|
||||
);
|
||||
}).export();
|
||||
const COOKIE_NAME_EXPORT = COOKIE_NAME;
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
COOKIE_NAME_EXPORT,
|
||||
authEnforcementMiddleware,
|
||||
authResolutionMiddleware
|
||||
});
|
||||
//# sourceMappingURL=auth.js.map
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../../src/lib/middlewares/auth.ts"],
|
||||
"sourcesContent": ["import { Middleware } from \"rjweb-server\";\nimport { type User } from \"@prisma/client\";\nimport { prisma } from \"../db\";\nimport { createLogger } from \"../logger\";\nimport { ERROR_MESSAGES } from \"../errors\";\n\nconst log = createLogger(\"AUTH\");\n\nconst COOKIE_NAME = \"pp_session\";\n\nexport type AuthState =\n | { success: true; user: User; sessionId: number }\n | { success: false; message: string; tokenProvided: boolean };\n\ntype AuthContext = {\n auth?: AuthState;\n};\n\nexport const authResolutionMiddleware = new Middleware<{}, AuthContext>(\n \"Auth Resolution Middleware\",\n \"1.0.0\",\n)\n .load(() => {\n log.info(\"Auth resolution middleware loaded\");\n })\n .httpRequest(async (_config, _server, context, ctr) => {\n const cookieToken = ctr.cookies.get(COOKIE_NAME);\n const tokenProvided = Boolean(cookieToken);\n const data = context.data(authResolutionMiddleware);\n\n if (!cookieToken) {\n data.auth = { success: false, message: \"No session\", tokenProvided: false };\n return;\n }\n\n const session = await prisma.session.findFirst({\n where: { hash: cookieToken },\n include: { user: true },\n });\n\n if (!session) {\n data.auth = { success: false, message: \"Invalid session\", tokenProvided };\n return;\n }\n\n data.auth = { success: true, user: session.user, sessionId: session.id };\n })\n .httpRequestContext(\n (_config, Original) =>\n class extends Original {\n getAuth(): AuthState {\n const data = this.context.data(authResolutionMiddleware);\n if (!data.auth) {\n return { success: false, message: \"Auth not resolved\", tokenProvided: false };\n }\n return data.auth;\n }\n },\n )\n .export();\n\nexport const authEnforcementMiddleware = new Middleware<{}, {}>(\n \"Auth Enforcement Middleware\",\n \"1.0.0\",\n)\n .httpRequest(async (_config, _server, context, ctr, end) => {\n const data = context.data(authResolutionMiddleware) as AuthContext;\n const auth = data.auth;\n\n if (!auth || auth.success || !auth.tokenProvided) {\n return;\n }\n\n return end(\n ctr.status(ERROR_MESSAGES.UNAUTHORIZED.code).print({\n status: \"FAILED\",\n message: auth.message,\n }),\n );\n })\n .export();\n\nexport const COOKIE_NAME_EXPORT = COOKIE_NAME;\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA2B;AAE3B,gBAAuB;AACvB,oBAA6B;AAC7B,oBAA+B;AAE/B,MAAM,UAAM,4BAAa,MAAM;AAE/B,MAAM,cAAc;AAUb,MAAM,2BAA2B,IAAI;AAAA,EAC1C;AAAA,EACA;AACF,EACG,KAAK,MAAM;AACV,MAAI,KAAK,mCAAmC;AAC9C,CAAC,EACA,YAAY,OAAO,SAAS,SAAS,SAAS,QAAQ;AACrD,QAAM,cAAc,IAAI,QAAQ,IAAI,WAAW;AAC/C,QAAM,gBAAgB,QAAQ,WAAW;AACzC,QAAM,OAAO,QAAQ,KAAK,wBAAwB;AAElD,MAAI,CAAC,aAAa;AAChB,SAAK,OAAO,EAAE,SAAS,OAAO,SAAS,cAAc,eAAe,MAAM;AAC1E;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,iBAAO,QAAQ,UAAU;AAAA,IAC7C,OAAO,EAAE,MAAM,YAAY;AAAA,IAC3B,SAAS,EAAE,MAAM,KAAK;AAAA,EACxB,CAAC;AAED,MAAI,CAAC,SAAS;AACZ,SAAK,OAAO,EAAE,SAAS,OAAO,SAAS,mBAAmB,cAAc;AACxE;AAAA,EACF;AAEA,OAAK,OAAO,EAAE,SAAS,MAAM,MAAM,QAAQ,MAAM,WAAW,QAAQ,GAAG;AACzE,CAAC,EACA;AAAA,EACC,CAAC,SAAS,aACR,cAAc,SAAS;AAAA,IACrB,UAAqB;AACnB,YAAM,OAAO,KAAK,QAAQ,KAAK,wBAAwB;AACvD,UAAI,CAAC,KAAK,MAAM;AACd,eAAO,EAAE,SAAS,OAAO,SAAS,qBAAqB,eAAe,MAAM;AAAA,MAC9E;AACA,aAAO,KAAK;AAAA,IACd;AAAA,EACF;AACJ,EACC,OAAO;AAEH,MAAM,4BAA4B,IAAI;AAAA,EAC3C;AAAA,EACA;AACF,EACG,YAAY,OAAO,SAAS,SAAS,SAAS,KAAK,QAAQ;AAC1D,QAAM,OAAO,QAAQ,KAAK,wBAAwB;AAClD,QAAM,OAAO,KAAK;AAElB,MAAI,CAAC,QAAQ,KAAK,WAAW,CAAC,KAAK,eAAe;AAChD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,IAAI,OAAO,6BAAe,aAAa,IAAI,EAAE,MAAM;AAAA,MACjD,QAAQ;AAAA,MACR,SAAS,KAAK;AAAA,IAChB,CAAC;AAAA,EACH;AACF,CAAC,EACA,OAAO;AAEH,MAAM,qBAAqB;",
|
||||
"names": []
|
||||
}
|
||||
Vendored
+40
@@ -0,0 +1,40 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var cors_exports = {};
|
||||
__export(cors_exports, {
|
||||
corsMiddleware: () => corsMiddleware
|
||||
});
|
||||
module.exports = __toCommonJS(cors_exports);
|
||||
var import_rjweb_server = require("rjweb-server");
|
||||
var import_env = require("../env");
|
||||
const ALLOWED_ORIGINS = /* @__PURE__ */ new Set([import_env.env.PP_BASE_URL]);
|
||||
const corsMiddleware = new import_rjweb_server.Middleware("CORS Middleware", "1.0.0").httpRequest(async (_config, _server, _context, ctr) => {
|
||||
const origin = ctr.headers.get("origin") || "";
|
||||
if (ALLOWED_ORIGINS.has(origin) || import_env.env.NODE_ENV === "development") {
|
||||
ctr.headers.set("Access-Control-Allow-Origin", origin || "*");
|
||||
ctr.headers.set("Access-Control-Allow-Credentials", "true");
|
||||
ctr.headers.set("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS");
|
||||
ctr.headers.set("Access-Control-Allow-Headers", "Content-Type,Authorization,X-Requested-With");
|
||||
}
|
||||
}).export();
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
corsMiddleware
|
||||
});
|
||||
//# sourceMappingURL=cors.js.map
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../../src/lib/middlewares/cors.ts"],
|
||||
"sourcesContent": ["import { Middleware } from \"rjweb-server\";\nimport { env } from \"../env\";\n\nconst ALLOWED_ORIGINS = new Set([env.PP_BASE_URL]);\n\nexport const corsMiddleware = new Middleware<{}, {}>(\"CORS Middleware\", \"1.0.0\")\n .httpRequest(async (_config, _server, _context, ctr) => {\n const origin = ctr.headers.get(\"origin\") || \"\";\n if (ALLOWED_ORIGINS.has(origin) || env.NODE_ENV === \"development\") {\n ctr.headers.set(\"Access-Control-Allow-Origin\", origin || \"*\");\n ctr.headers.set(\"Access-Control-Allow-Credentials\", \"true\");\n ctr.headers.set(\"Access-Control-Allow-Methods\", \"GET,POST,PUT,PATCH,DELETE,OPTIONS\");\n ctr.headers.set(\"Access-Control-Allow-Headers\", \"Content-Type,Authorization,X-Requested-With\");\n }\n })\n .export();\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA2B;AAC3B,iBAAoB;AAEpB,MAAM,kBAAkB,oBAAI,IAAI,CAAC,eAAI,WAAW,CAAC;AAE1C,MAAM,iBAAiB,IAAI,+BAAmB,mBAAmB,OAAO,EAC5E,YAAY,OAAO,SAAS,SAAS,UAAU,QAAQ;AACtD,QAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ,KAAK;AAC5C,MAAI,gBAAgB,IAAI,MAAM,KAAK,eAAI,aAAa,eAAe;AACjE,QAAI,QAAQ,IAAI,+BAA+B,UAAU,GAAG;AAC5D,QAAI,QAAQ,IAAI,oCAAoC,MAAM;AAC1D,QAAI,QAAQ,IAAI,gCAAgC,mCAAmC;AACnF,QAAI,QAAQ,IAAI,gCAAgC,6CAA6C;AAAA,EAC/F;AACF,CAAC,EACA,OAAO;",
|
||||
"names": []
|
||||
}
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
var __defProp = Object.defineProperty;
|
||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||
var __export = (target, all) => {
|
||||
for (var name in all)
|
||||
__defProp(target, name, { get: all[name], enumerable: true });
|
||||
};
|
||||
var __copyProps = (to, from, except, desc) => {
|
||||
if (from && typeof from === "object" || typeof from === "function") {
|
||||
for (let key of __getOwnPropNames(from))
|
||||
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||
}
|
||||
return to;
|
||||
};
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
var main_exports = {};
|
||||
__export(main_exports, {
|
||||
mainMiddleware: () => mainMiddleware
|
||||
});
|
||||
module.exports = __toCommonJS(main_exports);
|
||||
var import_rjweb_server = require("rjweb-server");
|
||||
var import_logger = require("../logger");
|
||||
const log = (0, import_logger.createLogger)("HTTP");
|
||||
const mainMiddleware = new import_rjweb_server.Middleware("Main Middleware", "1.0.0").load(() => {
|
||||
log.info("Main middleware loaded");
|
||||
}).httpRequest(async (_config, _server, _context, ctr) => {
|
||||
if (ctr.url.method === "OPTIONS") {
|
||||
ctr.status(204).print("");
|
||||
}
|
||||
}).export();
|
||||
// Annotate the CommonJS export names for ESM import in node:
|
||||
0 && (module.exports = {
|
||||
mainMiddleware
|
||||
});
|
||||
//# sourceMappingURL=main.js.map
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../../../src/lib/middlewares/main.ts"],
|
||||
"sourcesContent": ["import { Middleware } from \"rjweb-server\";\nimport { createLogger } from \"../logger\";\n\nconst log = createLogger(\"HTTP\");\n\nexport const mainMiddleware = new Middleware<{}, {}>(\"Main Middleware\", \"1.0.0\")\n .load(() => {\n log.info(\"Main middleware loaded\");\n })\n .httpRequest(async (_config, _server, _context, ctr) => {\n if (ctr.url.method === \"OPTIONS\") {\n ctr.status(204).print(\"\");\n }\n })\n .export();\n"],
|
||||
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAA2B;AAC3B,oBAA6B;AAE7B,MAAM,UAAM,4BAAa,MAAM;AAExB,MAAM,iBAAiB,IAAI,+BAAmB,mBAAmB,OAAO,EAC5E,KAAK,MAAM;AACV,MAAI,KAAK,wBAAwB;AACnC,CAAC,EACA,YAAY,OAAO,SAAS,SAAS,UAAU,QAAQ;AACtD,MAAI,IAAI,IAAI,WAAW,WAAW;AAChC,QAAI,OAAO,GAAG,EAAE,MAAM,EAAE;AAAA,EAC1B;AACF,CAAC,EACA,OAAO;",
|
||||
"names": []
|
||||
}
|
||||
Reference in New Issue
Block a user