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:
@@ -28,7 +28,7 @@ const permissionObjects = {
|
||||
type: 'string',
|
||||
},
|
||||
'additional-permissions': {
|
||||
type: 'array',
|
||||
type: 'boolean',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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] = []
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user