Merge pull request #24003 from grantila/grantila/azure-ad-handle-timeout-and-allow-disabling-photos

Azure AD, handle timeout and allow disabling photos
This commit is contained in:
Fredrik Adelöw
2024-04-09 13:47:30 +02:00
committed by GitHub
6 changed files with 51 additions and 12 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-msgraph': patch
---
Retry msgraph API calls, due to frequent ETIMEDOUT errors. Also allow disabling fetching user photos.
@@ -113,6 +113,7 @@ export class MicrosoftGraphClient {
requestRaw(
url: string,
headers?: Record<string, string>,
retryCount?: number,
): Promise<Response_2>;
}
@@ -210,6 +211,7 @@ export type MicrosoftGraphProviderConfig = {
groupSearch?: string;
groupSelect?: string[];
queryMode?: 'basic' | 'advanced';
loadUserPhotos?: boolean;
schedule?: TaskScheduleDefinition;
};
@@ -244,6 +246,7 @@ export function readMicrosoftGraphOrg(
userExpand?: string;
userFilter?: string;
userSelect?: string[];
loadUserPhotos?: boolean;
userGroupMemberSearch?: string;
userGroupMemberFilter?: string;
groupExpand?: string;
+5
View File
@@ -160,6 +160,11 @@ export interface Config {
* E.g. "accountEnabled eq true and userType eq 'member'"
*/
filter?: string;
/**
* Set to false to not load user photos.
* This can be useful for huge organizations.
*/
loadPhotos?: boolean;
};
group?: {
@@ -216,6 +216,7 @@ export class MicrosoftGraphClient {
async requestRaw(
url: string,
headers?: Record<string, string>,
retryCount = 2,
): Promise<Response> {
// Make sure that we always have a valid access token (might be cached)
const urlObj = new URL(url);
@@ -227,12 +228,19 @@ export class MicrosoftGraphClient {
throw new Error('Failed to obtain token from Azure Identity');
}
return await fetch(url, {
headers: {
...headers,
Authorization: `Bearer ${token.token}`,
},
});
try {
return await fetch(url, {
headers: {
...headers,
Authorization: `Bearer ${token.token}`,
},
});
} catch (e: any) {
if (e?.code === 'ETIMEDOUT' && retryCount > 0) {
return this.requestRaw(url, headers, retryCount - 1);
}
throw e;
}
}
/**
@@ -126,6 +126,12 @@ export type MicrosoftGraphProviderConfig = {
*/
queryMode?: 'basic' | 'advanced';
/**
* Set to false to not load user photos.
* This can be useful for huge organizations.
*/
loadUserPhotos?: boolean;
/**
* Schedule configuration for refresh tasks.
*/
@@ -280,6 +286,7 @@ export function readProviderConfig(
const userExpand = config.getOptionalString('user.expand');
const userFilter = config.getOptionalString('user.filter');
const userSelect = config.getOptionalStringArray('user.select');
const loadUserPhotos = config.getOptionalBoolean('user.loadPhotos');
const groupExpand = config.getOptionalString('group.expand');
const groupFilter = config.getOptionalString('group.filter');
@@ -335,6 +342,7 @@ export function readProviderConfig(
userExpand,
userFilter,
userSelect,
loadUserPhotos,
groupExpand,
groupFilter,
groupSearch,
@@ -49,6 +49,7 @@ export async function readMicrosoftGraphUsers(
userExpand?: string;
userFilter?: string;
userSelect?: string[];
loadUserPhotos?: boolean;
transformer?: UserTransformer;
logger: Logger;
},
@@ -70,6 +71,7 @@ export async function readMicrosoftGraphUsers(
client,
users,
options.logger,
options.loadUserPhotos,
options.transformer,
),
};
@@ -82,6 +84,7 @@ export async function readMicrosoftGraphUsersInGroups(
userExpand?: string;
userFilter?: string;
userSelect?: string[];
loadUserPhotos?: boolean;
userGroupMemberSearch?: string;
userGroupMemberFilter?: string;
groupExpand?: string;
@@ -145,6 +148,7 @@ export async function readMicrosoftGraphUsersInGroups(
client,
userGroupMembers.values(),
options.logger,
options.loadUserPhotos,
options.transformer,
),
};
@@ -366,6 +370,7 @@ export async function readMicrosoftGraphOrg(
userExpand?: string;
userFilter?: string;
userSelect?: string[];
loadUserPhotos?: boolean;
userGroupMemberSearch?: string;
userGroupMemberFilter?: string;
groupExpand?: string;
@@ -391,6 +396,7 @@ export async function readMicrosoftGraphOrg(
userSelect: options.userSelect,
userGroupMemberFilter: options.userGroupMemberFilter,
userGroupMemberSearch: options.userGroupMemberSearch,
loadUserPhotos: options.loadUserPhotos,
transformer: options.userTransformer,
logger: options.logger,
},
@@ -402,6 +408,7 @@ export async function readMicrosoftGraphOrg(
userExpand: options.userExpand,
userFilter: options.userFilter,
userSelect: options.userSelect,
loadUserPhotos: options.loadUserPhotos,
transformer: options.userTransformer,
logger: options.logger,
});
@@ -429,6 +436,7 @@ async function transformUsers(
client: MicrosoftGraphClient,
users: Iterable<MicrosoftGraph.User> | AsyncIterable<MicrosoftGraph.User>,
logger: Logger,
loadUserPhotos = true,
transformer?: UserTransformer,
) {
const limiter = limiterFactory(10);
@@ -443,12 +451,14 @@ async function transformUsers(
limiter(async () => {
let userPhoto;
try {
userPhoto = await client.getUserPhotoWithSizeLimit(
user.id!,
// We are limiting the photo size, as users with full resolution photos
// can make the Backstage API slow
120,
);
if (loadUserPhotos) {
userPhoto = await client.getUserPhotoWithSizeLimit(
user.id!,
// We are limiting the photo size, as users with full resolution photos
// can make the Backstage API slow
120,
);
}
} catch (e) {
logger.warn(`Unable to load user photo for`, {
user: user.id,