1
0
mirror of synced 2025-12-31 06:02:42 -05:00

Prog access data in rest reference docs (#49072)

Co-authored-by: Sarah Edwards <skedwards88@github.com>
Co-authored-by: Grace Park <gracepark@github.com>
This commit is contained in:
Rachael Sewell
2024-02-14 16:42:02 -08:00
committed by GitHub
parent 295c3347da
commit 3cc4a10b44
40 changed files with 66293 additions and 12223 deletions

View File

@@ -28,7 +28,7 @@ const permissionObjects = {
type: 'string',
},
'additional-permissions': {
type: 'array',
type: 'boolean',
},
},
}

View File

@@ -48,73 +48,78 @@ export async function syncGitHubAppsData(openApiSource, sourceSchemas, progAcces
const appDataOperationWithCategory = Object.assign({ category }, appDataOperation)
// server-to-server
if (isInstallationAccessToken) {
initAppData(githubAppsData['server-to-server-rest'], category, appDataOperation)
addAppData(githubAppsData['server-to-server-rest'], category, appDataOperation)
}
// user-to-server
if (isUserAccessToken) {
initAppData(githubAppsData['user-to-server-rest'], category, appDataOperation)
addAppData(githubAppsData['user-to-server-rest'], category, appDataOperation)
}
// fine-grained pat
if (isFineGrainedPat) {
initAppData(githubAppsData['fine-grained-pat'], category, appDataOperation)
addAppData(githubAppsData['fine-grained-pat'], category, appDataOperation)
}
// permissions
const allPermissions = {
...progAccessData[operation.operationId].permissions.and,
...progAccessData[operation.operationId].permissions.or,
}
for (const [permissionName, readOrWrite] of Object.entries(allPermissions)) {
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 relatedPermissionNames = Object.keys(
progAccessData[operation.operationId].permissions.and,
).filter((permission) => permission !== permissionName)
// github app permissions
const serverToServerPermissions = githubAppsData['server-to-server-permissions']
if (!serverToServerPermissions[permissionName]) {
serverToServerPermissions[permissionName] = {
title,
displayTitle,
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 worksWithData = {
'user-to-server': Boolean(isUserAccessToken),
'server-to-server': Boolean(isInstallationAccessToken),
'additional-permissions': relatedPermissionNames,
}
serverToServerPermissions[permissionName].permissions.push(
Object.assign({}, appDataOperationWithCategory, { access: readOrWrite }, worksWithData),
)
// fine-grained pats
if (isFineGrainedPat) {
const findGrainedPatPermissions = githubAppsData['fine-grained-pat-permissions']
if (!findGrainedPatPermissions[permissionName]) {
findGrainedPatPermissions[permissionName] = {
const title = progActorResources[permissionName]?.title || tempTitle
const resourceGroup = progActorResources[permissionName]?.resource_group || ''
const displayTitle = getDisplayTitle(title, resourceGroup)
const additionalPermissions =
progAccessData[operation.operationId].permissions.length > 1 ||
progAccessData[operation.operationId].permissions.some(
(permissionSet) => Object.keys(permissionSet).length > 1,
)
// github app permissions
const serverToServerPermissions = githubAppsData['server-to-server-permissions']
if (!serverToServerPermissions[permissionName]) {
serverToServerPermissions[permissionName] = {
title,
displayTitle,
permissions: [],
}
}
findGrainedPatPermissions[permissionName].permissions.push(
Object.assign({}, appDataOperationWithCategory, {
'additional-permissions': relatedPermissionNames,
access: readOrWrite,
}),
const worksWithData = {
'user-to-server': Boolean(isUserAccessToken),
'server-to-server': Boolean(isInstallationAccessToken),
'additional-permissions': additionalPermissions,
}
serverToServerPermissions[permissionName].permissions.push(
Object.assign(
{},
appDataOperationWithCategory,
{ access: readOrWrite },
worksWithData,
),
)
// fine-grained pats
if (isFineGrainedPat) {
const findGrainedPatPermissions = githubAppsData['fine-grained-pat-permissions']
if (!findGrainedPatPermissions[permissionName]) {
findGrainedPatPermissions[permissionName] = {
title,
displayTitle,
permissions: [],
}
}
findGrainedPatPermissions[permissionName].permissions.push(
Object.assign({}, appDataOperationWithCategory, {
'additional-permissions': additionalPermissions,
access: readOrWrite,
}),
)
}
}
}
}
@@ -148,23 +153,20 @@ export async function syncGitHubAppsData(openApiSource, sourceSchemas, progAcces
}
}
// When progAccessSource is defined, it will contain the root directory
// of the repo with the programmatic access file. If it is not defined,
// the file will be retrieved from the remote repo via the REST API.
async function getProgAccessData(progAccessSource) {
export async function getProgAccessData(progAccessSource = false) {
// check for required PAT
if (progAccessSource && !process.env.GITHUB_TOKEN) {
throw new Error(
'Error! You must have the GITHUB_TOKEN environment variable set to access the programmatic access and resource files via the GitHub REST API.',
)
}
let progAccessDataRaw
// config/locales/programmatic_actor_fine_grained_resources.en.yml
let progActorResources
const progAccessFilepath = 'config/access_control/programmatic_access.yaml'
const progActorFilepath = 'config/locales/programmatic_actor_fine_grained_resources.en.yml'
// check for required PAT
if (!process.env.GITHUB_TOKEN) {
throw new Error(
'Error! You must have the GITHUB_TOKEN environment variable set to access the programmatic access and resource files via the GitHub REST API.',
)
}
if (progAccessSource) {
progAccessDataRaw = yaml.load(
await readFile(path.join(progAccessSource, progAccessFilepath), 'utf8'),
@@ -183,54 +185,13 @@ async function getProgAccessData(progAccessSource) {
const progAccessData = {}
for (const operation of progAccessDataRaw) {
const permissions = { or: {}, and: {} }
if (operation.permission_sets) {
// Currently there is only a length of up to 2 permission_sets
// OR permission_sets are dashed lists in yaml
// e.g.
// permission_sets:
// - admin: write
// - contents: read
// This becomes: [{admin: write}, {contents: read}] with yaml.load
if (operation.permission_sets.length === 2) {
// There's currently only one scenario where you have an OR permission_set where one of the OR permissions is an AND permission_set
// In this scenario, we want the AND permission_set
if (
Object.keys(operation.permission_sets[0]).length > 1 ||
Object.keys(operation.permission_sets[1]).length > 1
) {
const andPermissionSet =
Object.keys(operation.permission_sets[0]).length > 1
? operation.permission_sets[0]
: operation.permission_sets[1]
Object.assign(permissions.and, andPermissionSet)
} else {
operation.permission_sets.forEach((permissionSet) => {
Object.assign(permissions.or, permissionSet)
})
}
// AND permission_sets are under the same dash in yaml
// e.g.
// permission_sets:
// - admin: write
// contents: read
// This becomes: [{admin: write, contents: read}] with yaml.load
} else if (operation.permission_sets.length === 1) {
Object.assign(permissions.and, operation.permission_sets[0])
}
}
const userToServerRest = operation.user_to_server.enabled
const serverToServer = operation.server_to_server.enabled
const allowPermissionlessAccess = operation.allows_permissionless_access
const disabledForPatV2 = operation.disabled_for_patv2
progAccessData[operation.operation_ids] = {
userToServerRest,
serverToServer,
permissions,
allowPermissionlessAccess,
disabledForPatV2,
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 || [],
allowPermissionlessAccess: operation.allows_permissionless_access,
allowsPublicRead: operation.allows_public_read,
}
}
return { progAccessData, progActorResources }
@@ -277,7 +238,7 @@ function sentenceCase(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
function initAppData(storage, category, data) {
function addAppData(storage, category, data) {
if (!storage[category]) {
storage[category] = []
}