diff --git a/Dockerfile b/Dockerfile index 5ba25ae..e775124 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ ARG COMMIT_HASH="" ENV APP_VERSION=$APP_VERSION ENV COMMIT_HASH=$COMMIT_HASH RUN apk add --no-cache python3 make g++ git -RUN corepack enable +RUN corepack enable && corepack prepare pnpm@11.6.0 --activate COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ COPY packages ./packages COPY scripts ./scripts @@ -16,7 +16,9 @@ RUN CI=true pnpm prune --prod && pnpm install --prod --frozen-lockfile --ignore- FROM node:24-alpine WORKDIR /app ENV NODE_ENV=production +ENV PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false RUN apk add --no-cache libstdc++ +RUN corepack enable && corepack prepare pnpm@11.6.0 --activate COPY --from=builder /app/package.json ./package.json COPY --from=builder /app/pnpm-lock.yaml ./pnpm-lock.yaml COPY --from=builder /app/pnpm-workspace.yaml ./pnpm-workspace.yaml diff --git a/packages/admin-ui/src/pages/ClientEdit.tsx b/packages/admin-ui/src/pages/ClientEdit.tsx index 99547a9..1d82a00 100644 --- a/packages/admin-ui/src/pages/ClientEdit.tsx +++ b/packages/admin-ui/src/pages/ClientEdit.tsx @@ -40,8 +40,9 @@ const parseList = (v: string) => .filter(Boolean); const DEFAULT_DASHBOARD_EMOJI = "🚀"; const DEFAULT_DASHBOARD_LETTER = "D"; -type ScopeRow = { key: string; description: string }; +type ScopeRow = { id: string; key: string; description: string }; const CLIENT_EDIT_TABS = ["identity", "dashboard", "security", "token", "oauth", "crypto"]; +let scopeRowId = 0; function deliveredKeyKindFor(version: Client["keyDeliveryVersion"]): Client["deliveredKeyKind"] { return version === "v1-drk" ? "root_key" : "client_app_key"; @@ -53,7 +54,8 @@ function isClientEditTab(value: string | null): value is (typeof CLIENT_EDIT_TAB } function normalizeScopeRows(scopes: ClientScope[]): ScopeRow[] { - return scopes.map((scope) => ({ + return scopes.map((scope, index) => ({ + id: `scope-${index}-${scopeRowId++}`, key: scope.key, description: scope.description || "", })); @@ -61,11 +63,15 @@ function normalizeScopeRows(scopes: ClientScope[]): ScopeRow[] { function buildDefaultScopes(): ScopeRow[] { return [ - { key: "openid", description: "Authenticate you" }, - { key: "profile", description: "Access your profile information" }, + { id: "default-openid", key: "openid", description: "Authenticate you" }, + { id: "default-profile", key: "profile", description: "Access your profile information" }, ]; } +function buildEmptyScope(): ScopeRow { + return { id: `scope-${scopeRowId++}`, key: "", description: "" }; +} + function FieldLabel({ title, tooltip }: { title: string; tooltip: string }) { return (
@@ -342,7 +348,7 @@ export default function ClientEdit({ mode = "edit" }: ClientEditProps) { const addScope = () => { setForm((current) => ({ ...current, - scopes: [...current.scopes, { key: "", description: "" }], + scopes: [...current.scopes, buildEmptyScope()], })); }; @@ -1162,7 +1168,7 @@ export default function ClientEdit({ mode = "edit" }: ClientEditProps) { {form.scopes.map((scope, index) => ( - + { await expect(page.getByRole('heading', { name: 'Create Client' })).toBeVisible(); await fillField(page, 'Client ID', clientId); await fillField(page, 'Name', 'Admin UI Key Delivery Client'); + await page.getByRole('tab', { name: 'OAuth' }).click(); + const scopeKeyInput = page.getByPlaceholder('openid').first(); + await scopeKeyInput.fill('custom-scope'); + await expect(scopeKeyInput).toBeFocused(); + await page.keyboard.type('-extra'); + await expect(scopeKeyInput).toHaveValue('custom-scope-extra'); await page.getByRole('tab', { name: 'Security' }).click(); await selectField(page, page, 'ZK Delivery', 'fragment-jwe'); await selectField(page, page, 'ZK Required', 'Yes');