Files
zerobyte/app/server/modules/system/system.controller.ts
Nico d7bcf4c9e2 feat: display updates and release notes (#290)
* feat: display notification when new release is available

* refactor: standalone re-usable cache util

* refactor: clear cache on server startup

* refactor: add timeout to gh release fetch

* fix: run with app version env variable
2026-01-04 10:19:23 +01:00

65 lines
1.8 KiB
TypeScript

import { Hono } from "hono";
import { validator } from "hono-openapi";
import {
downloadResticPasswordBodySchema,
downloadResticPasswordDto,
getUpdatesDto,
systemInfoDto,
type SystemInfoDto,
type UpdateInfoDto,
} from "./system.dto";
import { systemService } from "./system.service";
import { requireAuth } from "../auth/auth.middleware";
import { RESTIC_PASS_FILE } from "../../core/constants";
import { db } from "../../db/db";
import { usersTable } from "../../db/schema";
import { eq } from "drizzle-orm";
export const systemController = new Hono()
.use(requireAuth)
.get("/info", systemInfoDto, async (c) => {
const info = await systemService.getSystemInfo();
return c.json<SystemInfoDto>(info, 200);
})
.get("/updates", getUpdatesDto, async (c) => {
const updates = await systemService.getUpdates();
return c.json<UpdateInfoDto>(updates, 200);
})
.post(
"/restic-password",
downloadResticPasswordDto,
validator("json", downloadResticPasswordBodySchema),
async (c) => {
const user = c.get("user");
const body = c.req.valid("json");
const [dbUser] = await db.select().from(usersTable).where(eq(usersTable.id, user.id));
if (!dbUser) {
return c.json({ message: "User not found" }, 401);
}
const isValid = await Bun.password.verify(body.password, dbUser.passwordHash);
if (!isValid) {
return c.json({ message: "Incorrect password" }, 401);
}
try {
const file = Bun.file(RESTIC_PASS_FILE);
const content = await file.text();
await db.update(usersTable).set({ hasDownloadedResticPassword: true }).where(eq(usersTable.id, user.id));
c.header("Content-Type", "text/plain");
c.header("Content-Disposition", 'attachment; filename="restic.pass"');
return c.text(content);
} catch (_error) {
return c.json({ message: "Failed to read Restic password file" }, 500);
}
},
);