Simplify middleware and remove unused code

- Remove unused orgMemberMiddleware (org procedures use helper functions)
- Remove orgMemberProcedure from base.ts
- Simplify superuserMiddleware using inline concat syntax
- Import OrgInfo/OrgMembership from context.ts instead of redefining

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
igm
2026-01-12 18:06:25 +08:00
parent 73ef3df01f
commit d8397dfb38
5 changed files with 7 additions and 133 deletions

View File

@@ -4,6 +4,5 @@
export { authMiddleware } from "./auth.js"; export { authMiddleware } from "./auth.js";
export { loginRequestMiddleware } from "./login-request.js"; export { loginRequestMiddleware } from "./login-request.js";
export { orgMemberMiddleware } from "./org-member.js";
export { os } from "./os.js"; export { os } from "./os.js";
export { superuserMiddleware } from "./superuser.js"; export { superuserMiddleware } from "./superuser.js";

View File

@@ -1,87 +0,0 @@
/**
* Org member middleware - authenticates and verifies org membership
*
* This middleware chains authMiddleware first, then looks up the org
* and verifies the user is a member. Adds org and membership to context.
*
* Input must include `slug` (the org slug).
*/
import type {
AuthenticatedContext,
OrgInfo,
OrgMembership,
} from "../context.js";
import { ORPCError } from "@orpc/server";
import { authMiddleware } from "./auth.js";
import { os } from "./os.js";
interface OrgSlugInput {
slug: string;
}
const orgMemberCheck = os.middleware(
async (
{
context,
next,
}: {
context: AuthenticatedContext;
next: (opts: {
context: { org: OrgInfo; membership: OrgMembership };
}) => Promise<unknown>;
},
input: OrgSlugInput,
) => {
const { db } = context;
const { slug } = input;
// Look up org by slug
const org = await db
.selectFrom("orgs")
.select(["id", "slug", "display_name", "logo_url", "created_at"])
.where("slug", "=", slug)
.executeTakeFirst();
if (!org) {
throw new ORPCError("NOT_FOUND", { message: "Organization not found" });
}
// Check user membership
const membership = await db
.selectFrom("org_members")
.select(["id", "role", "created_at"])
.where("org_id", "=", org.id)
.where("user_id", "=", context.user.id)
.executeTakeFirst();
if (!membership) {
throw new ORPCError("FORBIDDEN", {
message: "You are not a member of this organization",
});
}
const orgInfo: OrgInfo = {
id: org.id,
slug: org.slug,
displayName: org.display_name,
logoUrl: org.logo_url,
createdAt: org.created_at,
};
const membershipInfo: OrgMembership = {
id: membership.id,
role: membership.role,
createdAt: membership.created_at,
};
return next({
context: {
org: orgInfo,
membership: membershipInfo,
},
});
},
);
export const orgMemberMiddleware = authMiddleware.concat(orgMemberCheck);

View File

@@ -4,19 +4,11 @@
* This middleware chains authMiddleware first, then checks for superuser. * This middleware chains authMiddleware first, then checks for superuser.
*/ */
import type { AuthenticatedContext } from "../context.js";
import { ORPCError } from "@orpc/server"; import { ORPCError } from "@orpc/server";
import { authMiddleware } from "./auth.js"; import { authMiddleware } from "./auth.js";
import { os } from "./os.js";
const superuserCheck = os.middleware( export const superuserMiddleware = authMiddleware.concat(
async ({ async ({ context, next }) => {
context,
next,
}: {
context: AuthenticatedContext;
next: () => Promise<unknown>;
}) => {
if (!context.user.isSuperuser) { if (!context.user.isSuperuser) {
throw new ORPCError("FORBIDDEN", { throw new ORPCError("FORBIDDEN", {
message: "Superuser access required", message: "Superuser access required",
@@ -25,5 +17,3 @@ const superuserCheck = os.middleware(
return next(); return next();
}, },
); );
export const superuserMiddleware = authMiddleware.concat(superuserCheck);

View File

@@ -9,35 +9,21 @@ import type {
APIContext, APIContext,
AuthenticatedContext, AuthenticatedContext,
LoginRequestContext, LoginRequestContext,
OrgMemberContext,
} from "../context.js"; } from "../context.js";
import { import {
authMiddleware, authMiddleware,
loginRequestMiddleware, loginRequestMiddleware,
orgMemberMiddleware,
os, os,
superuserMiddleware, superuserMiddleware,
} from "../middlewares/index.js"; } from "../middlewares/index.js";
// Re-export middlewares and os // Re-export middlewares and os
export { export { authMiddleware, loginRequestMiddleware, os, superuserMiddleware };
authMiddleware,
loginRequestMiddleware,
orgMemberMiddleware,
os,
superuserMiddleware,
};
// Pre-configured procedures with middleware applied // Pre-configured procedures with middleware applied
export const authedProcedure = os.use(authMiddleware); export const authedProcedure = os.use(authMiddleware);
export const superuserProcedure = os.use(superuserMiddleware); export const superuserProcedure = os.use(superuserMiddleware);
export const loginRequestProcedure = os.use(loginRequestMiddleware); export const loginRequestProcedure = os.use(loginRequestMiddleware);
export const orgMemberProcedure = os.use(orgMemberMiddleware);
// Type exports for use in procedure files // Type exports for use in procedure files
export type { export type { APIContext, AuthenticatedContext, LoginRequestContext };
APIContext,
AuthenticatedContext,
LoginRequestContext,
OrgMemberContext,
};

View File

@@ -3,27 +3,13 @@
* Provides org lookup, membership verification, and role checks * Provides org lookup, membership verification, and role checks
*/ */
import type { OrgInfo, OrgMembership } from "../../context.js";
import type { DB, OrgRole } from "@reviq/db-schema"; import type { DB, OrgRole } from "@reviq/db-schema";
import type { Kysely } from "kysely"; import type { Kysely } from "kysely";
import { ORPCError } from "@orpc/server"; import { ORPCError } from "@orpc/server";
// ===== Types ===== // Re-export types for convenience
export type { OrgInfo, OrgMembership };
/** Org info returned from lookup */
export interface OrgInfo {
id: number;
slug: string;
displayName: string;
logoUrl: string | null;
createdAt: Date;
}
/** User's membership in an org */
export interface OrgMembership {
id: number;
role: OrgRole;
createdAt: Date;
}
// ===== Role Hierarchy ===== // ===== Role Hierarchy =====