feat: tiered costs feature + admin tier management + tag selection
Build & Push Docker Image / build (push) Successful in 6m52s
Build & Push Docker Image / build (push) Successful in 6m52s
- costs: nullable notes (fix create without notes), drop renewalDate (schema + API + UI), gate POST/PATCH/DELETE to admin + costs feature - feature middleware: admin-aware hasFeature + getEntitlements union; /auth/me and login return resolved entitlements - users: tier enum (free/premium/enterprise) in create/update/list, admin UI tier select + tier badge - tags: GET /tags/all, TagInput autocomplete in new/edit tool forms, feature suggestions on focus, query invalidation on create/update - openapi: nullable ToolUpdate urls, ToolUpdate tier fields, listAllTags - Dockerfile: push-force to drop renewal_date column
This commit is contained in:
@@ -6,9 +6,19 @@ const TIER_FEATURES: Record<string, string[]> = {
|
||||
enterprise: ["browse", "rate", "search", "similar-tools", "costs", "redundancy", "analytics-advanced", "sso", "audit-export", "api-access"],
|
||||
};
|
||||
|
||||
export function hasFeature(tier: string | undefined, feature: string): boolean {
|
||||
const features = TIER_FEATURES[tier ?? "free"] ?? TIER_FEATURES.free;
|
||||
return features.includes(feature);
|
||||
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) {
|
||||
@@ -17,7 +27,7 @@ export function requireFeature(feature: string) {
|
||||
res.status(401).json({ error: "Authentication required" });
|
||||
return;
|
||||
}
|
||||
if (!hasFeature(req.session.user.tier, feature)) {
|
||||
if (!hasFeature(req.session.user.tier, feature, req.session.user.role)) {
|
||||
res.status(403).json({ error: `Feature "${feature}" requires a higher tier` });
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user