3 Commits

Author SHA1 Message Date
e136c07928 Add some stub user stuff 2026-01-03 17:06:54 -06:00
c926f15aab Fix circular dependency breaking ncc bundle
Don't export authRoutes from barrel file to break the cycle:
services.ts → auth/index.ts → auth/routes.ts → services.ts

Import authRoutes directly from ./auth/routes instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 14:24:53 -06:00
39cd93c81e Move services.ts 2026-01-03 14:12:27 -06:00
5 changed files with 53 additions and 6 deletions

View File

@@ -1,3 +1,4 @@
{"id":"diachron-2vh","title":"Add unit testing to golang programs","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T12:31:41.281891462-06:00","created_by":"mw","updated_at":"2026-01-03T12:31:41.281891462-06:00"} {"id":"diachron-2vh","title":"Add unit testing to golang programs","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T12:31:41.281891462-06:00","created_by":"mw","updated_at":"2026-01-03T12:31:41.281891462-06:00"}
{"id":"diachron-64w","title":"Add unit testing to express backend","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T12:31:30.439206099-06:00","created_by":"mw","updated_at":"2026-01-03T12:31:30.439206099-06:00"} {"id":"diachron-64w","title":"Add unit testing to express backend","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T12:31:30.439206099-06:00","created_by":"mw","updated_at":"2026-01-03T12:31:30.439206099-06:00"}
{"id":"diachron-fzd","title":"Add generic 'user' functionality","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T12:35:53.73213604-06:00","created_by":"mw","updated_at":"2026-01-03T12:35:53.73213604-06:00"} {"id":"diachron-fzd","title":"Add generic 'user' functionality","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T12:35:53.73213604-06:00","created_by":"mw","updated_at":"2026-01-03T12:35:53.73213604-06:00"}
{"id":"diachron-ngx","title":"Teach the master and/or build process to send messages with notify-send when builds fail or succeed. Ideally this will be fairly generic.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-03T14:10:11.773218844-06:00","created_by":"mw","updated_at":"2026-01-03T14:10:11.773218844-06:00"}

View File

@@ -1,9 +1,12 @@
// index.ts // index.ts
// //
// Barrel export for auth module. // Barrel export for auth module.
//
// NOTE: authRoutes is NOT exported here to avoid circular dependency:
// services.ts → auth/index.ts → auth/routes.ts → services.ts
// Import authRoutes directly from "./auth/routes" instead.
export { hashPassword, verifyPassword } from "./password"; export { hashPassword, verifyPassword } from "./password";
export { authRoutes } from "./routes";
export { AuthService } from "./service"; export { AuthService } from "./service";
export { type AuthStore, InMemoryAuthStore } from "./store"; export { type AuthStore, InMemoryAuthStore } from "./store";
export { generateToken, hashToken, SESSION_COOKIE_NAME } from "./token"; export { generateToken, hashToken, SESSION_COOKIE_NAME } from "./token";

View File

@@ -2,7 +2,7 @@
import nunjucks from "nunjucks"; import nunjucks from "nunjucks";
import { DateTime } from "ts-luxon"; import { DateTime } from "ts-luxon";
import { authRoutes } from "./auth"; import { authRoutes } from "./auth/routes";
import { contentTypes } from "./content-types"; import { contentTypes } from "./content-types";
import { multiHandler } from "./handlers"; import { multiHandler } from "./handlers";
import { HttpCode, httpCodes } from "./http-codes"; import { HttpCode, httpCodes } from "./http-codes";
@@ -59,6 +59,29 @@ const routes: Route[] = [
}; };
}, },
}, },
{
path: "/whoami",
methods: ["GET"],
handler: async (_call: Call): Promise<Result> => {
const me = services.session.getUser();
const template = `
<html>
<head></head>
<body>
{{ me }}
</body>
</html>
`;
const result = nunjucks.renderString(template, { me });
return {
code: httpCodes.success.OK,
contentType: contentTypes.text.html,
result,
};
},
},
{ {
path: "/ok", path: "/ok",
methods: ["GET", "POST", "PUT"], methods: ["GET", "POST", "PUT"],

View File

@@ -1,8 +1,9 @@
// services.ts // services.ts
import { AuthService, InMemoryAuthStore } from "./auth"; import { AuthService, InMemoryAuthStore } from "../auth";
import { config } from "./config"; import { config } from "../config";
import { getLogs, log } from "./logging"; import { getLogs, log } from "../logging";
import { AnonymousUser, anonymousUser, type User } from "../user";
//const database = Client({ //const database = Client({
@@ -27,16 +28,24 @@ const misc = {
}, },
}; };
const session = {
getUser: (): User => {
return anonymousUser;
},
};
// Initialize auth with in-memory store // Initialize auth with in-memory store
const authStore = new InMemoryAuthStore(); const authStore = new InMemoryAuthStore();
const auth = new AuthService(authStore); const auth = new AuthService(authStore);
// Keep this asciibetically sorted
const services = { const services = {
auth,
database, database,
logging, logging,
misc, misc,
random, random,
auth, session,
}; };
export { services }; export { services };

View File

@@ -181,8 +181,19 @@ export class User {
toJSON(): UserData { toJSON(): UserData {
return { ...this.data }; return { ...this.data };
} }
toString(): string {
return `User(id ${this.id})`;
}
} }
// For representing "no user" in contexts where user is optional // For representing "no user" in contexts where user is optional
export const AnonymousUser = Symbol("AnonymousUser"); export const AnonymousUser = Symbol("AnonymousUser");
export const anonymousUser = User.create("anonymous@example.com", {
id: "-1",
displayName: "Anonymous User",
// FIXME: set createdAt and updatedAt to start of epoch
});
export type MaybeUser = User | typeof AnonymousUser; export type MaybeUser = User | typeof AnonymousUser;