Files
tool-evaluator/artifacts/api-server/src/middleware/feature.ts
T
opencode c77610786b
Build & Push Docker Image / build (push) Successful in 2m47s
feat: compare (premium), rating-history trend, hover previews
2026-08-02 12:48:02 +02:00

37 lines
1.4 KiB
TypeScript

import { type Request, type Response, type NextFunction } from "express";
const TIER_FEATURES: Record<string, string[]> = {
free: ["browse", "rate", "search"],
premium: ["browse", "rate", "search", "similar-tools", "costs", "redundancy", "analytics-advanced", "trash", "compare", "watchlist"],
enterprise: ["browse", "rate", "search", "similar-tools", "costs", "redundancy", "analytics-advanced", "trash", "compare", "watchlist", "sso", "audit-export", "api-access"],
};
export function getEntitlements(tier: string | undefined, role: string | undefined): string[] {
if (role === "admin") {
const all = new Set<string>();
for (const features of Object.values(TIER_FEATURES)) {
for (const f of features) all.add(f);
}
return [...all];
}
return TIER_FEATURES[tier ?? "free"] ?? TIER_FEATURES.free;
}
export function hasFeature(tier: string | undefined, feature: string, role?: string): boolean {
return getEntitlements(tier, role).includes(feature);
}
export function requireFeature(feature: string) {
return (req: Request, res: Response, next: NextFunction): void => {
if (!req.session.user) {
res.status(401).json({ error: "Authentication required" });
return;
}
if (!hasFeature(req.session.user.tier, feature, req.session.user.role)) {
res.status(403).json({ error: `Feature "${feature}" requires a higher tier` });
return;
}
next();
};
}