From b42d33ea2de52b2fc2de8a0c467a569cf9633684 Mon Sep 17 00:00:00 2001 From: Grace Park Date: Thu, 23 May 2024 14:40:35 -0700 Subject: [PATCH] Update wording for fine-grained tokens on REST (#50753) --- data/ui.yml | 8 +- src/fixtures/fixtures/data/ui.yml | 8 +- src/github-apps/scripts/sync.js | 56 +- src/rest/components/RestAuth.tsx | 10 +- src/rest/data/fpt-2022-11-28/schema.json | 1606 +++++++-------- src/rest/data/ghec-2022-11-28/schema.json | 1754 ++++++++--------- .../data/ghes-3.10-2022-11-28/schema.json | 1380 ++++++------- .../data/ghes-3.11-2022-11-28/schema.json | 1404 ++++++------- .../data/ghes-3.12-2022-11-28/schema.json | 1414 ++++++------- .../data/ghes-3.13-2022-11-28/schema.json | 1464 +++++++------- src/rest/data/ghes-3.9-2022-11-28/schema.json | 1346 ++++++------- src/rest/scripts/utils/sync.js | 2 +- 12 files changed, 5238 insertions(+), 5214 deletions(-) diff --git a/data/ui.yml b/data/ui.yml index 777ba62c4b..59e6355b70 100644 --- a/data/ui.yml +++ b/data/ui.yml @@ -168,10 +168,10 @@ rest_reference: button_text: copy_to_clipboard: Copy to clipboard copied: Copied! - works_with_tokens: 'This endpoint works with the following token types' - permission_sets: 'The token must have at least one of the following permission sets' - permission_set: 'The token must have the following permission set' - no_permission_sets: 'The token does not require any permissions.' + works_with_fine_grained_tokens: 'This endpoint works with the following fine-grained token types' + permission_sets: 'The fine-grained token must have at least one of the following permission sets' + permission_set: 'The fine-grained token must have the following permission set' + no_permission_sets: 'The fine-grained token does not require any permissions.' allows_public_read_access: This endpoint can be used without authentication or the aforementioned permissions if only public resources are requested. allows_public_read_access_no_permissions: This endpoint can be used without authentication if only public resources are requested. user_access_token_name: GitHub App user access tokens diff --git a/src/fixtures/fixtures/data/ui.yml b/src/fixtures/fixtures/data/ui.yml index 777ba62c4b..59e6355b70 100644 --- a/src/fixtures/fixtures/data/ui.yml +++ b/src/fixtures/fixtures/data/ui.yml @@ -168,10 +168,10 @@ rest_reference: button_text: copy_to_clipboard: Copy to clipboard copied: Copied! - works_with_tokens: 'This endpoint works with the following token types' - permission_sets: 'The token must have at least one of the following permission sets' - permission_set: 'The token must have the following permission set' - no_permission_sets: 'The token does not require any permissions.' + works_with_fine_grained_tokens: 'This endpoint works with the following fine-grained token types' + permission_sets: 'The fine-grained token must have at least one of the following permission sets' + permission_set: 'The fine-grained token must have the following permission set' + no_permission_sets: 'The fine-grained token does not require any permissions.' allows_public_read_access: This endpoint can be used without authentication or the aforementioned permissions if only public resources are requested. allows_public_read_access_no_permissions: This endpoint can be used without authentication if only public resources are requested. user_access_token_name: GitHub App user access tokens diff --git a/src/github-apps/scripts/sync.js b/src/github-apps/scripts/sync.js index eaf8465be2..fa98462598 100644 --- a/src/github-apps/scripts/sync.js +++ b/src/github-apps/scripts/sync.js @@ -64,16 +64,7 @@ export async function syncGitHubAppsData(openApiSource, sourceSchemas, progAcces // permissions for (const permissionSet of progAccessData[operation.operationId].permissions) { for (const [permissionName, readOrWrite] of Object.entries(permissionSet)) { - const tempTitle = permissionName.replace(/_/g, ' ') - const permissionNameExists = progActorResources[permissionName] - if (!permissionNameExists) { - console.warn( - `The permission ${permissionName} is missing from config/locales/programmatic_actor_fine_grained_resources.en.yml. Creating a placeholder value of ${tempTitle} until it's added.`, - ) - } - const title = progActorResources[permissionName]?.title || tempTitle - const resourceGroup = progActorResources[permissionName]?.resource_group || '' - const displayTitle = getDisplayTitle(title, resourceGroup) + const { title, displayTitle } = getDisplayTitle(permissionName, progActorResources) const additionalPermissions = progAccessData[operation.operationId].permissions.length > 1 || progAccessData[operation.operationId].permissions.some( @@ -153,7 +144,7 @@ export async function syncGitHubAppsData(openApiSource, sourceSchemas, progAcces } } -export async function getProgAccessData(progAccessSource) { +export async function getProgAccessData(progAccessSource, isRest = false) { const useRemoteGitHubFiles = progAccessSource === 'rest-api-description' // check for required PAT if (useRemoteGitHubFiles && !process.env.GITHUB_TOKEN) { @@ -189,14 +180,31 @@ export async function getProgAccessData(progAccessSource) { userToServerRest: operation.user_to_server.enabled, serverToServer: operation.server_to_server.enabled, fineGrainedPat: operation.user_to_server.enabled && !operation.disabled_for_patv2, - permissions: operation.permission_sets || [], + permissions: isRest + ? getDisplayPermissions(operation.permission_sets || [], progActorResources) + : operation.permission_sets || [], allowPermissionlessAccess: operation.allows_permissionless_access, allowsPublicRead: operation.allows_public_read, } } + return { progAccessData, progActorResources } } +function getDisplayPermissions(permissionSets, progActorResources) { + const displayPermissions = permissionSets.map((permissionSet) => { + const displayPermissionSet = {} + Object.entries(permissionSet).forEach(([key, value]) => { + const { displayTitle } = getDisplayTitle(key, progActorResources, true) + displayPermissionSet[displayTitle] = value + }) + + return displayPermissionSet + }) + + return displayPermissions +} + function sortObjectByKeys(obj) { return Object.keys(obj) .sort() @@ -223,15 +231,31 @@ function sortObjectByTitle(obj) { }, {}) } -function getDisplayTitle(title, resourceGroup) { +function getDisplayTitle(permissionName, progActorResources, isRest = false) { + const tempTitle = permissionName.replace(/_/g, ' ') + const permissionNameExists = progActorResources[permissionName] + if (!permissionNameExists) { + console.warn( + `The permission ${permissionName} is missing from config/locales/programmatic_actor_fine_grained_resources.en.yml. Creating a placeholder value of ${tempTitle} until it's added.`, + ) + } + const title = progActorResources[permissionName]?.title || tempTitle + const resourceGroup = progActorResources[permissionName]?.resource_group || '' + if (!title) { console.warn(`No title found for title ${title} resource group ${resourceGroup}`) return '' } - return !resourceGroup - ? sentenceCase(title) + ' permissions' - : sentenceCase(resourceGroup) + ' permissions for ' + `"${title}"` + const displayTitle = isRest + ? !resourceGroup + ? sentenceCase(title) + ' permissions' + : `"${sentenceCase(title)}" ` + resourceGroup + ' permissions' + : !resourceGroup + ? sentenceCase(title) + ' permissions' + : sentenceCase(resourceGroup) + ' permissions for ' + `"${title}"` + + return { title, displayTitle } } function sentenceCase(str) { diff --git a/src/rest/components/RestAuth.tsx b/src/rest/components/RestAuth.tsx index f761574587..59cafc0a27 100644 --- a/src/rest/components/RestAuth.tsx +++ b/src/rest/components/RestAuth.tsx @@ -54,14 +54,14 @@ export function RestAuth({ progAccess, slug, heading }: Props) { ? t('allows_public_read_access_no_permissions') : t('allows_public_read_access') // progAccess.permissions is an array of objects - // For example: [ {'actions': 'read', 'packages': 'read'}, {'read': 'repo'} ] + // For example: [ {'"Actions" repository permissions': 'read', '"Administration" organization permissions': 'write'}, {'"Secrets" organization permissions"': 'write'} ] // Each object represents a set of permissions containing one // or more key-value pairs. All permissions in a set are required. // If there is more than one set of permissions, any set can be used. const formattedPermissions = progAccess.permissions.map((permissionSet: Object, index) => { // Given the example above, the first object is now an array of tuples - // [['actions', 'read'], ['packages', 'read']] - // that can be formatted as a string like `actions:read` and `packages:read` + // [['"Actions" repository permissions', 'read'], ['"Administration" organization permissions', 'read']] + // that can be formatted as a string like `"Administration" organization permissions (write)' const permissionSetPairs = Object.entries(permissionSet) const numPermissionSetPairs = permissionSetPairs.length @@ -69,7 +69,7 @@ export function RestAuth({ progAccess, slug, heading }: Props) {
  • {permissionSetPairs.map(([key, value], setIndex) => ( - {key + ':' + value} + {`${key} (${value})`} {setIndex < numPermissionSetPairs - 1 && and } ))} @@ -79,7 +79,7 @@ export function RestAuth({ progAccess, slug, heading }: Props) { const fineGrainedData = ( <> -

    {t('works_with_tokens')}:

    +

    {t('works_with_fine_grained_tokens')}: