diff --git a/plugins/catalog-backend-module-github-org/src/module.ts b/plugins/catalog-backend-module-github-org/src/module.ts index 2d349cb873..e6179e07f1 100644 --- a/plugins/catalog-backend-module-github-org/src/module.ts +++ b/plugins/catalog-backend-module-github-org/src/module.ts @@ -121,6 +121,7 @@ export const catalogModuleGithubOrgEntityProvider = createBackendModule({ alwaysUseDefaultNamespace: definitions.length === 1 && definition.orgs?.length === 1, pageSizes: definition.pageSizes, + excludeSuspendedUsers: definition.excludeSuspendedUsers, }), ); } @@ -133,6 +134,7 @@ function readDefinitionsFromConfig(rootConfig: Config): Array<{ id: string; githubUrl: string; orgs?: string[]; + excludeSuspendedUsers?: boolean; schedule: SchedulerServiceTaskScheduleDefinition; pageSizes?: { teams?: number; @@ -154,6 +156,8 @@ function readDefinitionsFromConfig(rootConfig: Config): Array<{ id: c.getString('id'), githubUrl: c.getString('githubUrl'), orgs: c.getOptionalStringArray('orgs'), + excludeSuspendedUsers: + c.getOptionalBoolean('excludeSuspendedUsers') ?? false, schedule: readSchedulerServiceTaskScheduleDefinitionFromConfig( c.getConfig('schedule'), ), diff --git a/plugins/catalog-backend-module-github/config.d.ts b/plugins/catalog-backend-module-github/config.d.ts index f3cbb15e06..6277f7aa2e 100644 --- a/plugins/catalog-backend-module-github/config.d.ts +++ b/plugins/catalog-backend-module-github/config.d.ts @@ -264,6 +264,13 @@ export interface Config { */ orgs?: string[]; + /** + * (Optional) Only for GitHub Enterprise. Whether to exclude suspended users when querying organization users. + * If true, the defaultTransformer will not return suspended users. + * Default: `false`. + */ + excludeSuspendedUsers?: boolean; + /** * The refresh schedule to use. */ @@ -315,6 +322,13 @@ export interface Config { */ orgs?: string[]; + /** + * (Optional) Only for GitHub Enterprise. Whether to exclude suspended users when querying organization users. + * If true, the defaultTransformer will not return suspended users. + * Default: `false`. + */ + excludeSuspendedUsers?: boolean; + /** * The refresh schedule to use. */ diff --git a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts index 6befd32056..02f5052ae1 100644 --- a/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts +++ b/plugins/catalog-backend-module-github/src/lib/defaultTransformers.ts @@ -62,6 +62,9 @@ export const defaultUserTransformer = async ( item: GithubUser, _ctx: TransformerContext, ): Promise => { + if (item.suspendedAt) { + return undefined; + } const entity: UserEntity = { apiVersion: 'backstage.io/v1alpha1', kind: 'User', diff --git a/plugins/catalog-backend-module-github/src/lib/github.ts b/plugins/catalog-backend-module-github/src/lib/github.ts index 625fb57bba..b614b4be64 100644 --- a/plugins/catalog-backend-module-github/src/lib/github.ts +++ b/plugins/catalog-backend-module-github/src/lib/github.ts @@ -117,6 +117,7 @@ export type GithubUser = { email?: string; name?: string; organizationVerifiedDomainEmails?: string[]; + suspendedAt?: string; }; /** @@ -186,9 +187,11 @@ export async function getOrganizationUsers( client: typeof graphql, org: string, tokenType: GithubCredentialType, + excludeSuspendedUsers: boolean = false, userTransformer: UserTransformer = defaultUserTransformer, pageSizes: GithubPageSizes = DEFAULT_PAGE_SIZES, ): Promise<{ users: Entity[] }> { + const suspendedAtField = excludeSuspendedUsers ? 'suspendedAt,' : ''; const query = ` query users($org: String!, $email: Boolean!, $cursor: String, $organizationMembersPageSize: Int!) { organization(login: $org) { @@ -200,6 +203,7 @@ export async function getOrganizationUsers( email @include(if: $email), login, name, + ${suspendedAtField} organizationVerifiedDomainEmails(login: $org) } } diff --git a/plugins/catalog-backend-module-github/src/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend-module-github/src/processors/GithubMultiOrgReaderProcessor.ts index 8af528dfcf..058ce2cb6c 100644 --- a/plugins/catalog-backend-module-github/src/processors/GithubMultiOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-github/src/processors/GithubMultiOrgReaderProcessor.ts @@ -148,6 +148,7 @@ export class GithubMultiOrgReaderProcessor implements CatalogProcessor { client, orgConfig.name, tokenType, + false, async (githubUser, ctx): Promise => { const result = this.options.userTransformer ? await this.options.userTransformer(githubUser, ctx) diff --git a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts index 839ca66e40..bb0dd84c6f 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubMultiOrgEntityProvider.ts @@ -174,6 +174,14 @@ export interface GithubMultiOrgEntityProviderOptions { * Reduce these values if hitting RESOURCE_LIMITS_EXCEEDED errors. */ pageSizes?: Partial; + + /** + * Optionally exclude suspended users when querying organization users. + * @defaultValue false + * @remarks + * Only for GitHub Enterprise instances. Will error if used against GitHub.com API. + */ + excludeSuspendedUsers?: boolean; } type CreateDeltaOperation = (entities: Entity[]) => { @@ -221,6 +229,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { events: options.events, alwaysUseDefaultNamespace: options.alwaysUseDefaultNamespace, pageSizes: options.pageSizes, + excludeSuspendedUsers: options.excludeSuspendedUsers, }); provider.schedule(options.schedule); @@ -241,6 +250,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { teamTransformer?: TeamTransformer; alwaysUseDefaultNamespace?: boolean; pageSizes?: Partial; + excludeSuspendedUsers?: boolean; }, ) {} @@ -304,6 +314,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { client, org, tokenType, + this.options.excludeSuspendedUsers, this.options.userTransformer, pageSizes, ); @@ -456,6 +467,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { client, org, tokenType, + this.options.excludeSuspendedUsers, this.options.userTransformer, pageSizes, ); @@ -690,6 +702,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider { client, org, tokenType, + this.options.excludeSuspendedUsers, this.options.userTransformer, pageSizes, ); diff --git a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts index 6dfa8a07f8..31b6dc338b 100644 --- a/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts +++ b/plugins/catalog-backend-module-github/src/providers/GithubOrgEntityProvider.ts @@ -130,6 +130,14 @@ export interface GithubOrgEntityProviderOptions { * Optionally include a team transformer for transforming from GitHub teams to Group Entities */ teamTransformer?: TeamTransformer; + + /** + * Optionally exclude suspended users when querying organization users. + * @defaultValue false + * @remarks + * Only for GitHub Enterprise instances. Will error if used against GitHub.com API. + */ + excludeSuspendedUsers?: boolean; } /** @@ -167,6 +175,7 @@ export class GithubOrgEntityProvider implements EntityProvider { userTransformer: options.userTransformer, teamTransformer: options.teamTransformer, events: options.events, + excludeSuspendedUsers: options.excludeSuspendedUsers, }); provider.schedule(options.schedule); @@ -184,6 +193,7 @@ export class GithubOrgEntityProvider implements EntityProvider { githubCredentialsProvider?: GithubCredentialsProvider; userTransformer?: UserTransformer; teamTransformer?: TeamTransformer; + excludeSuspendedUsers?: boolean; }, ) { this.credentialsProvider = @@ -235,6 +245,7 @@ export class GithubOrgEntityProvider implements EntityProvider { client, org, tokenType, + this.options.excludeSuspendedUsers, this.options.userTransformer, ); const { teams } = await getOrganizationTeams( @@ -363,6 +374,7 @@ export class GithubOrgEntityProvider implements EntityProvider { client, org, tokenType, + this.options.excludeSuspendedUsers, this.options.userTransformer, ); @@ -454,6 +466,7 @@ export class GithubOrgEntityProvider implements EntityProvider { client, org, tokenType, + this.options.excludeSuspendedUsers, this.options.userTransformer, );