feat: add auth.ts
This commit is contained in:
parent
6fc9af3dc5
commit
4bddb6cc34
1 changed files with 60 additions and 0 deletions
60
auth.ts
Normal file
60
auth.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Minimal partner token auth for agentify-help standalone app.
|
||||
* Replaces server/partner-api-routes.ts validatePartnerToken.
|
||||
*/
|
||||
import { pool } from "./db.js";
|
||||
import crypto from "crypto";
|
||||
|
||||
function hashToken(token: string): string {
|
||||
return crypto.createHash("sha256").update(token).digest("hex");
|
||||
}
|
||||
|
||||
export interface PartnerTokenContext {
|
||||
id: number;
|
||||
partner_name: string;
|
||||
permissions: string[];
|
||||
area_codes: string[] | null;
|
||||
}
|
||||
|
||||
export async function validatePartnerToken(
|
||||
authHeader: string | undefined
|
||||
): Promise<PartnerTokenContext | null> {
|
||||
if (!authHeader?.startsWith("Bearer ws_")) return null;
|
||||
const token = authHeader.slice(7);
|
||||
if (!token.startsWith("ws_")) return null;
|
||||
|
||||
const hash = hashToken(token);
|
||||
const result = await pool.query(
|
||||
`SELECT id, partner_name, permissions, area_codes
|
||||
FROM partner_api_tokens
|
||||
WHERE token_hash = $1 AND active = true AND revoked_at IS NULL
|
||||
LIMIT 1`,
|
||||
[hash]
|
||||
);
|
||||
if (!result.rows.length) return null;
|
||||
|
||||
const r = result.rows[0];
|
||||
pool.query(
|
||||
`UPDATE partner_api_tokens SET last_used_at = NOW(), use_count = use_count + 1 WHERE id = $1`,
|
||||
[r.id]
|
||||
).catch(() => {});
|
||||
|
||||
return {
|
||||
id: r.id,
|
||||
partner_name: r.partner_name,
|
||||
permissions: (r.permissions as string[]) || [],
|
||||
area_codes: r.area_codes || null,
|
||||
};
|
||||
}
|
||||
|
||||
export function requirePermission(permission: string) {
|
||||
return async (req: any, res: any, next: any) => {
|
||||
const ctx = await validatePartnerToken(req.headers.authorization).catch(() => null);
|
||||
if (!ctx) return res.status(401).json({ error: "Unauthorized" });
|
||||
if (!ctx.permissions.includes(permission) && !ctx.permissions.includes("geo.seed")) {
|
||||
return res.status(403).json({ error: "Forbidden", required: permission });
|
||||
}
|
||||
(req as any).partner = ctx;
|
||||
next();
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue