Minimale git-remote met publiek/prive-toggle

main

Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.

2.6 kB Ruw bestand
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";

import express from "express";

import { identify } from "./auth.ts";
import { config } from "./config.ts";
import { publishSnapshot } from "./git.ts";
import { listRepos } from "./repos.ts";
import { adminRouter } from "./routes/admin.ts";
import { gitHttpHandler } from "./routes/smart-http.ts";
import { repoBrowser, repoIndex, sendError } from "./routes/web.ts";

const here = path.dirname(fileURLToPath(import.meta.url));
const publicDir = path.resolve(here, "..", "public");

const app = express();
app.disable("x-powered-by");
if (config.trustProxy) app.set("trust proxy", true);

app.use((_req, res, next) => {
  res.setHeader(
    "Content-Security-Policy",
    "default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self' data: https:; frame-ancestors 'none'; base-uri 'none'; form-action 'self'",
  );
  res.setHeader("X-Content-Type-Options", "nosniff");
  res.setHeader("Referrer-Policy", "same-origin");
  next();
});

app.use(identify);

// Het git-transport moet de ruwe request-body kunnen streamen, dus dit staat
// bewust vóór express.urlencoded — die zou de stream anders al opgeslurpt hebben.
app.use(config.gitPrefix, gitHttpHandler(false));
app.use(config.gitFullPrefix, gitHttpHandler(true));

app.use("/assets", express.static(publicDir, { maxAge: "1h", index: false }));
app.use(express.urlencoded({ extended: false, limit: "64kb" }));

app.use(adminRouter);
app.get("/", repoIndex);
app.use("/r", repoBrowser);

app.use((req, res) => {
  sendError(req, res, 404, "Deze pagina bestaat niet.");
});

app.use(
  (
    error: Error,
    req: express.Request,
    res: express.Response,
    _next: express.NextFunction,
  ): void => {
    console.error(error);
    if (res.headersSent) {
      res.end();
      return;
    }
    sendError(req, res, 500, "Er ging iets mis op de server.");
  },
);

await fs.mkdir(config.repoRoot, { recursive: true });

// Zorgt dat elke repository een publieke momentopname heeft, ook eentje die er al
// stond voordat dit bestond. Ongewijzigde inhoud levert geen nieuwe commit op.
for (const repo of await listRepos()) {
  try {
    await publishSnapshot(repo.dir, repo.publishedDir);
  } catch (error) {
    console.error(`[publish] ${repo.name}: momentopname bijwerken mislukt`, error);
  }
}

app.listen(config.port, config.host, () => {
  console.log(`pub-repo luistert op http://${config.host}:${config.port}`);
  console.log(`repositories in ${config.repoRoot}`);
  console.log(`clone-URL's: ${config.publicUrl}${config.gitPrefix}/<naam>.git`);
});