fix: Fix the auth API middleware

This commit is contained in:
Wanjohi
2025-10-27 01:23:14 +03:00
parent 53390524ff
commit ef5e626c9d
4 changed files with 68 additions and 34 deletions

View File

@@ -3,27 +3,26 @@ import { Context } from "./context.js";
import { ErrorCodes, VisibleError } from "./error.js"; import { ErrorCodes, VisibleError } from "./error.js";
export namespace Actor { export namespace Actor {
export interface Member { export interface User {
type: "member"; type: "user";
properties: { properties: {
userID: string;
email: string; email: string;
teamID: string;
memberID: string;
}; };
} }
export interface Team { export interface Steam {
type: "team"; type: "steam";
properties: { properties: {
teamID: string; userID: string;
email: string; steamID: string;
}; };
} }
export interface System { export interface System {
type: "system"; type: "system";
properties: { properties: {
teamID: string; userID: string;
}; };
} }
@@ -40,13 +39,13 @@ export namespace Actor {
properties: {}; properties: {};
} }
export type Info = Team | Member | Public | Token | System; export type Info = Steam | User | Public | Token | System;
export const ctx = Context.create<Info>(); export const ctx = Context.create<Info>();
export function teamID() { export function userID() {
const actor = ctx.use(); const actor = ctx.use();
if ("teamID" in actor.properties) return actor.properties.teamID; if ("userID" in actor.properties) return actor.properties.userID;
throw new VisibleError( throw new VisibleError(
"authentication", "authentication",
ErrorCodes.Authentication.UNAUTHORIZED, ErrorCodes.Authentication.UNAUTHORIZED,

View File

@@ -22,7 +22,6 @@ export namespace Examples {
id: "74839300282033", // Steam ID id: "74839300282033", // Steam ID
ownerID: User.id, ownerID: User.id,
name: "JD The 65th", name: "JD The 65th",
username: "jdoe",
realName: "John Doe", realName: "John Doe",
memberSince: new Date("2010-01-26T21:00:00.000Z"), memberSince: new Date("2010-01-26T21:00:00.000Z"),
avatarHash: "3a5e805fd4c1e04e26a97af0b9c6fab2dee91a19", avatarHash: "3a5e805fd4c1e04e26a97af0b9c6fab2dee91a19",

View File

@@ -1,6 +1,10 @@
import { z } from "zod/v4"; import { z } from "zod/v4";
import { Examples } from "../examples.js"; import { Examples } from "../examples.js";
import { Limitations } from "./steam.sql.js"; import { Limitations, steamTable } from "./steam.sql.js";
import { fn } from "../utils/fn.js";
import { Actor } from "../actor.js";
import { Database } from "../drizzle/index.js";
import { eq, isNull, and } from "drizzle-orm";
export namespace Steam { export namespace Steam {
export const Info = z export const Info = z
@@ -18,10 +22,6 @@ export namespace Steam {
description: "The display name of the Steam account", description: "The display name of the Steam account",
example: Examples.SteamAccount.name, example: Examples.SteamAccount.name,
}), }),
username: z.string().meta({
description: "The username of the Steam account",
example: Examples.SteamAccount.username,
}),
realName: z.string().nullable().meta({ realName: z.string().nullable().meta({
description: "The real name associated with the Steam account", description: "The real name associated with the Steam account",
example: Examples.SteamAccount.realName, example: Examples.SteamAccount.realName,
@@ -38,7 +38,7 @@ export namespace Steam {
description: "Account limitations and restrictions", description: "Account limitations and restrictions",
example: Examples.SteamAccount.limitations, example: Examples.SteamAccount.limitations,
}), }),
profileUrl: z.string().meta({ profileUrl: z.string().nullable().meta({
description: "The Steam community profile URL or identifier", description: "The Steam community profile URL or identifier",
example: Examples.SteamAccount.profileUrl, example: Examples.SteamAccount.profileUrl,
}), }),
@@ -54,4 +54,38 @@ export namespace Steam {
}); });
export type Info = z.infer<typeof Info>; export type Info = z.infer<typeof Info>;
export const fromID = fn(Info.shape.id, async (id) => {
const userID = Actor.userID();
return Database.transaction((tx) =>
tx
.select()
.from(steamTable)
.where(
and(
eq(steamTable.id, id),
eq(steamTable.ownerID, userID),
isNull(steamTable.timeDeleted),
),
)
.then((rows) => rows.map(serialize).at(0)),
);
});
export function serialize(
input: typeof steamTable.$inferSelect,
): z.infer<typeof Info> {
return {
id: input.id,
name: input.name,
ownerID: input.ownerID,
realName: input.realName,
profileUrl: input.profileUrl,
memberSince: input.memberSince,
avatarHash: input.avatarHash,
limitations: input.limitations,
lastSyncedAt: input.lastSyncedAt,
};
}
} }

View File

@@ -2,13 +2,13 @@ import { subjects } from "@/subjects";
import { MiddlewareHandler } from "hono"; import { MiddlewareHandler } from "hono";
import { Actor } from "@nestri/core/actor"; import { Actor } from "@nestri/core/actor";
import { Api } from "@nestri/core/api/index"; import { Api } from "@nestri/core/api/index";
import { Member } from "@nestri/core/member/index"; import { Steam } from "@nestri/core/steam/index";
import { createClient } from "@openauthjs/openauth/client"; import { createClient } from "@openauthjs/openauth/client";
import { VisibleError, ErrorCodes } from "@nestri/core/error"; import { VisibleError, ErrorCodes } from "@nestri/core/error";
const client = createClient({ const client = createClient({
clientID: "api", clientID: "api",
issuer: process.env.AUTH_URL, issuer: process.env.AUTH_URL || "http://localhost:3000",
subjects, subjects,
}); });
@@ -52,15 +52,14 @@ export const auth: MiddlewareHandler = async (c, next) => {
ErrorCodes.Authentication.INVALID_TOKEN, ErrorCodes.Authentication.INVALID_TOKEN,
"Invalid bearer token", "Invalid bearer token",
); );
if (result.subject.type === "team") { if (result.subject.type === "user") {
const memberID = const steamID = c.req.header("x-nestri-steam") || c.req.query("steamID");
c.req.header("x-nestri-member") || c.req.query("memberID"); if (!steamID) {
if (!memberID) {
return Actor.provide( return Actor.provide(
"team", "user",
{ {
email: result.subject.properties.email, email: result.subject.properties.email,
teamID: result.subject.properties.teamID, userID: result.subject.properties.userID,
}, },
next, next,
); );
@@ -69,17 +68,20 @@ export const auth: MiddlewareHandler = async (c, next) => {
return Actor.provide( return Actor.provide(
"system", "system",
{ {
teamID: result.subject.properties.teamID, userID: result.subject.properties.userID,
}, },
async () => { async () => {
const member = await Member.fromID(email); const steamAcc = await Steam.fromID(steamID);
if (!member || member.timeDeleted) { if (!steamAcc) {
c.status(401); throw new VisibleError(
return c.text("Unauthorized: User not found"); "authentication",
ErrorCodes.Authentication.INVALID_TOKEN,
"Invalid bearer token",
);
} }
return Actor.provide( return Actor.provide(
"member", "steam",
{ memberID: member.id, teamID: member.workspaceID }, { steamID: steamAcc.id, userID: steamAcc.ownerID },
next, next,
); );
}, },