Files
nicktrn 5447cf4843 feat(webapp): admin UI for feature flag overrides (#3291)
Adds a dialog to the admin orgs page for viewing and editing per-org
feature flag overrides. Flags are introspected from the catalog so the
UI stays in sync with available flags automatically. Also adds a new tab
for global flags.

Refactors featureFlags.server.ts to split catalog definition (shared)
from server-only runtime (flags(), makeSetMultipleFlags). The shared
module exports flag metadata and validation so both the UI and API
routes can use it without pulling in server dependencies.
2026-03-30 16:55:23 +01:00

49 lines
1.2 KiB
TypeScript

import { prisma } from "~/db.server";
import { env } from "~/env.server";
import { FEATURE_FLAG } from "~/v3/featureFlags";
import { makeFlag } from "~/v3/featureFlags.server";
export async function canAccessQuery(options: {
userId: string;
isAdmin: boolean;
isImpersonating: boolean;
organizationSlug: string;
}): Promise<boolean> {
const { userId, isAdmin, isImpersonating, organizationSlug } = options;
// 1. If it's on then we have access
const globallyEnabled = env.QUERY_FEATURE_ENABLED === "1";
if (globallyEnabled) {
return true;
}
// 2. Admins always have access
if (isAdmin || isImpersonating) {
return true;
}
// 3. Check if org/global feature flag is on
const org = await prisma.organization.findFirst({
where: {
slug: organizationSlug,
members: { some: { userId } },
},
select: {
featureFlags: true,
},
});
const flag = makeFlag();
const flagResult = await flag({
key: FEATURE_FLAG.hasQueryAccess,
defaultValue: false,
overrides: (org?.featureFlags as Record<string, unknown>) ?? {},
});
if (flagResult) {
return true;
}
// 4. Not enabled anywhere
return false;
}