@backstage/plugin-catalog-backend-module-msgraph 0.5.26-next.2 → 0.5.27-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @backstage/plugin-catalog-backend-module-msgraph
2
2
 
3
+ ## 0.5.27-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/backend-tasks@0.5.24-next.0
9
+ - @backstage/backend-common@0.22.1-next.0
10
+ - @backstage/backend-plugin-api@0.6.19-next.0
11
+ - @backstage/plugin-catalog-node@1.12.1-next.0
12
+ - @backstage/catalog-model@1.5.0
13
+ - @backstage/config@1.2.0
14
+ - @backstage/plugin-catalog-common@1.0.23
15
+
16
+ ## 0.5.26
17
+
18
+ ### Patch Changes
19
+
20
+ - 49eab29: Fixed disabling of user photo fetching. Previously, the config value wasn't propagated properly, so user photos was still being fetched despite disabled by config.
21
+ - 6e370e6: Handle fetching huge amounts of users from Azure without crashing
22
+ - Updated dependencies
23
+ - @backstage/plugin-catalog-node@1.12.0
24
+ - @backstage/catalog-model@1.5.0
25
+ - @backstage/backend-common@0.22.0
26
+ - @backstage/backend-plugin-api@0.6.18
27
+ - @backstage/backend-tasks@0.5.23
28
+ - @backstage/plugin-catalog-common@1.0.23
29
+
3
30
  ## 0.5.26-next.2
4
31
 
5
32
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-backend-module-msgraph",
3
- "version": "0.5.26-next.2",
3
+ "version": "0.5.27-next.0",
4
4
  "main": "../dist/alpha.cjs.js",
5
5
  "types": "../dist/alpha.d.ts"
6
6
  }
package/dist/alpha.cjs.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var backendPluginApi = require('@backstage/backend-plugin-api');
6
6
  var alpha = require('@backstage/plugin-catalog-node/alpha');
7
- var MicrosoftGraphOrgEntityProvider = require('./cjs/MicrosoftGraphOrgEntityProvider-DZcLVfiM.cjs.js');
7
+ var MicrosoftGraphOrgEntityProvider = require('./cjs/MicrosoftGraphOrgEntityProvider-Cyc0qWct.cjs.js');
8
8
  require('@backstage/plugin-catalog-node');
9
9
  require('@azure/identity');
10
10
  require('node-fetch');
@@ -75,8 +75,8 @@ class MicrosoftGraphClient {
75
75
  * @param queryMode - Mode to use while querying. Some features are only available at "advanced".
76
76
  */
77
77
  async *requestCollection(path, query, queryMode) {
78
- const appliedQueryMode = (query == null ? void 0 : query.search) ? "advanced" : queryMode != null ? queryMode : "basic";
79
- if (appliedQueryMode === "advanced" && ((query == null ? void 0 : query.filter) || (query == null ? void 0 : query.select))) {
78
+ const appliedQueryMode = query?.search ? "advanced" : queryMode ?? "basic";
79
+ if (appliedQueryMode === "advanced" && (query?.filter || query?.select)) {
80
80
  query.count = true;
81
81
  }
82
82
  const headers = appliedQueryMode === "advanced" ? {
@@ -108,15 +108,14 @@ class MicrosoftGraphClient {
108
108
  * @param headers - optional HTTP headers
109
109
  */
110
110
  async requestApi(path, query, headers) {
111
- var _a;
112
111
  const queryString = qs__default.default.stringify(
113
112
  {
114
- $search: query == null ? void 0 : query.search,
115
- $filter: query == null ? void 0 : query.filter,
116
- $select: (_a = query == null ? void 0 : query.select) == null ? void 0 : _a.join(","),
117
- $expand: query == null ? void 0 : query.expand,
118
- $count: query == null ? void 0 : query.count,
119
- $top: query == null ? void 0 : query.top
113
+ $search: query?.search,
114
+ $filter: query?.filter,
115
+ $select: query?.select?.join(","),
116
+ $expand: query?.expand,
117
+ $count: query?.count,
118
+ $top: query?.top
120
119
  },
121
120
  {
122
121
  addQueryPrefix: true,
@@ -151,7 +150,7 @@ class MicrosoftGraphClient {
151
150
  }
152
151
  });
153
152
  } catch (e) {
154
- if ((e == null ? void 0 : e.code) === "ETIMEDOUT" && retryCount > 0) {
153
+ if (e?.code === "ETIMEDOUT" && retryCount > 0) {
155
154
  return this.requestRaw(url, headers, retryCount - 1);
156
155
  }
157
156
  throw e;
@@ -315,12 +314,11 @@ class MicrosoftGraphClient {
315
314
  const DEFAULT_PROVIDER_ID = "default";
316
315
  const DEFAULT_TARGET = "https://graph.microsoft.com/v1.0";
317
316
  function readMicrosoftGraphConfig(config) {
318
- var _a, _b;
319
317
  const providers = [];
320
- const providerConfigs = (_a = config.getOptionalConfigArray("providers")) != null ? _a : [];
318
+ const providerConfigs = config.getOptionalConfigArray("providers") ?? [];
321
319
  for (const providerConfig of providerConfigs) {
322
320
  const target = lodash.trimEnd(
323
- (_b = providerConfig.getOptionalString("target")) != null ? _b : DEFAULT_TARGET,
321
+ providerConfig.getOptionalString("target") ?? DEFAULT_TARGET,
324
322
  "/"
325
323
  );
326
324
  const authority = providerConfig.getOptionalString("authority");
@@ -401,9 +399,8 @@ function readProviderConfigs(config) {
401
399
  });
402
400
  }
403
401
  function readProviderConfig(id, config) {
404
- var _a;
405
402
  const target = lodash.trimEnd(
406
- (_a = config.getOptionalString("target")) != null ? _a : DEFAULT_TARGET,
403
+ config.getOptionalString("target") ?? DEFAULT_TARGET,
407
404
  "/"
408
405
  );
409
406
  const authority = config.getOptionalString("authority");
@@ -605,14 +602,10 @@ function buildOrgHierarchy(groups) {
605
602
  function buildMemberOf(groups, users) {
606
603
  const groupsByName = new Map(groups.map((g) => [g.metadata.name, g]));
607
604
  users.forEach((user) => {
608
- var _a;
609
605
  const transitiveMemberOf = /* @__PURE__ */ new Set();
610
606
  const todo = [
611
- ...(_a = user.spec.memberOf) != null ? _a : [],
612
- ...groups.filter((g) => {
613
- var _a2;
614
- return (_a2 = g.spec.members) == null ? void 0 : _a2.includes(user.metadata.name);
615
- }).map((g) => g.metadata.name)
607
+ ...user.spec.memberOf ?? [],
608
+ ...groups.filter((g) => g.spec.members?.includes(user.metadata.name)).map((g) => g.metadata.name)
616
609
  ];
617
610
  for (; ; ) {
618
611
  const current = todo.pop();
@@ -622,7 +615,7 @@ function buildMemberOf(groups, users) {
622
615
  if (!transitiveMemberOf.has(current)) {
623
616
  transitiveMemberOf.add(current);
624
617
  const group = groupsByName.get(current);
625
- if (group == null ? void 0 : group.spec.parent) {
618
+ if (group?.spec.parent) {
626
619
  todo.push(group.spec.parent);
627
620
  }
628
621
  }
@@ -706,36 +699,34 @@ async function readMicrosoftGraphUsersInGroups(client, options) {
706
699
  };
707
700
  }
708
701
  async function readMicrosoftGraphOrganization(client, tenantId, options) {
709
- var _a;
710
702
  const organization = await client.getOrganization(tenantId);
711
- const transformer = (_a = options == null ? void 0 : options.transformer) != null ? _a : defaultOrganizationTransformer;
703
+ const transformer = options?.transformer ?? defaultOrganizationTransformer;
712
704
  const rootGroup = await transformer(organization);
713
705
  return { rootGroup };
714
706
  }
715
707
  async function readMicrosoftGraphGroups(client, tenantId, options) {
716
- var _a;
717
708
  const groups = [];
718
709
  const groupMember = /* @__PURE__ */ new Map();
719
710
  const groupMemberOf = /* @__PURE__ */ new Map();
720
711
  const limiter = limiterFactory__default.default(10);
721
712
  const { rootGroup } = await readMicrosoftGraphOrganization(client, tenantId, {
722
- transformer: options == null ? void 0 : options.organizationTransformer
713
+ transformer: options?.organizationTransformer
723
714
  });
724
715
  if (rootGroup) {
725
716
  groupMember.set(rootGroup.metadata.name, /* @__PURE__ */ new Set());
726
717
  groups.push(rootGroup);
727
718
  }
728
- const transformer = (_a = options == null ? void 0 : options.groupTransformer) != null ? _a : defaultGroupTransformer;
719
+ const transformer = options?.groupTransformer ?? defaultGroupTransformer;
729
720
  const promises = [];
730
721
  for await (const group of client.getGroups(
731
722
  {
732
- expand: options == null ? void 0 : options.groupExpand,
733
- filter: options == null ? void 0 : options.groupFilter,
734
- search: options == null ? void 0 : options.groupSearch,
735
- select: options == null ? void 0 : options.groupSelect,
723
+ expand: options?.groupExpand,
724
+ filter: options?.groupFilter,
725
+ search: options?.groupSearch,
726
+ select: options?.groupSelect,
736
727
  top: PAGE_SIZE
737
728
  },
738
- options == null ? void 0 : options.queryMode
729
+ options?.queryMode
739
730
  )) {
740
731
  promises.push(
741
732
  limiter(async () => {
@@ -805,8 +796,7 @@ function resolveRelations(rootGroup, groups, users, groupMember, groupMemberOf)
805
796
  });
806
797
  }
807
798
  groups.forEach((group) => {
808
- var _a;
809
- const id = (_a = group.metadata.annotations[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION]) != null ? _a : group.metadata.annotations[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];
799
+ const id = group.metadata.annotations[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ?? group.metadata.annotations[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];
810
800
  retrieveItems(groupMember, id).forEach((m) => {
811
801
  const childGroup = groupMap.get(m);
812
802
  if (childGroup) {
@@ -881,7 +871,7 @@ async function readMicrosoftGraphOrg(client, tenantId, options) {
881
871
  }
882
872
  async function transformUsers(client, users, logger, loadUserPhotos = true, transformer) {
883
873
  const limiter = limiterFactory__default.default(10);
884
- const resolvedTransformer = transformer != null ? transformer : defaultUserTransformer;
874
+ const resolvedTransformer = transformer ?? defaultUserTransformer;
885
875
  const promises = [];
886
876
  const entities = [];
887
877
  for await (const user of users) {
@@ -926,22 +916,15 @@ function ensureItem(target, key, value) {
926
916
  set.add(value);
927
917
  }
928
918
  function retrieveItems(target, key) {
929
- var _a;
930
- return (_a = target.get(key)) != null ? _a : /* @__PURE__ */ new Set();
919
+ return target.get(key) ?? /* @__PURE__ */ new Set();
931
920
  }
932
921
 
933
- var __defProp = Object.defineProperty;
934
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
935
- var __publicField = (obj, key, value) => {
936
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
937
- return value;
938
- };
939
922
  class MicrosoftGraphOrgEntityProvider {
940
923
  constructor(options) {
941
924
  this.options = options;
942
- __publicField(this, "connection");
943
- __publicField(this, "scheduleFn");
944
925
  }
926
+ connection;
927
+ scheduleFn;
945
928
  static fromConfig(configRoot, options) {
946
929
  if ("id" in options) {
947
930
  return [
@@ -958,13 +941,12 @@ class MicrosoftGraphOrgEntityProvider {
958
941
  return transformers[id];
959
942
  }
960
943
  return readProviderConfigs(configRoot).map((providerConfig) => {
961
- var _a;
962
944
  if (!options.schedule && !providerConfig.schedule) {
963
945
  throw new Error(
964
946
  `No schedule provided neither via code nor config for MicrosoftGraphOrgEntityProvider:${providerConfig.id}.`
965
947
  );
966
948
  }
967
- const taskRunner = (_a = options.schedule) != null ? _a : options.scheduler.createScheduledTaskRunner(providerConfig.schedule);
949
+ const taskRunner = options.schedule ?? options.scheduler.createScheduledTaskRunner(providerConfig.schedule);
968
950
  const provider = new MicrosoftGraphOrgEntityProvider({
969
951
  id: providerConfig.id,
970
952
  provider: providerConfig,
@@ -1027,20 +1009,18 @@ class MicrosoftGraphOrgEntityProvider {
1027
1009
  }
1028
1010
  /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */
1029
1011
  async connect(connection) {
1030
- var _a;
1031
1012
  this.connection = connection;
1032
- await ((_a = this.scheduleFn) == null ? void 0 : _a.call(this));
1013
+ await this.scheduleFn?.();
1033
1014
  }
1034
1015
  /**
1035
1016
  * Runs one complete ingestion loop. Call this method regularly at some
1036
1017
  * appropriate cadence.
1037
1018
  */
1038
1019
  async read(options) {
1039
- var _a;
1040
1020
  if (!this.connection) {
1041
1021
  throw new Error("Not initialized");
1042
1022
  }
1043
- const logger = (_a = options == null ? void 0 : options.logger) != null ? _a : this.options.logger;
1023
+ const logger = options?.logger ?? this.options.logger;
1044
1024
  const provider = this.options.provider;
1045
1025
  const { markReadComplete } = trackProgress(logger);
1046
1026
  const client = MicrosoftGraphClient.create(this.options.provider);
@@ -1117,8 +1097,7 @@ function trackProgress(logger) {
1117
1097
  return { markReadComplete };
1118
1098
  }
1119
1099
  function withLocations(providerId, entity) {
1120
- var _a, _b, _c;
1121
- const uid = ((_a = entity.metadata.annotations) == null ? void 0 : _a[MICROSOFT_GRAPH_USER_ID_ANNOTATION]) || ((_b = entity.metadata.annotations) == null ? void 0 : _b[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION]) || ((_c = entity.metadata.annotations) == null ? void 0 : _c[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION]) || entity.metadata.name;
1100
+ const uid = entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] || entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] || entity.metadata.annotations?.[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION] || entity.metadata.name;
1122
1101
  const location = `msgraph:${providerId}/${encodeURIComponent(uid)}`;
1123
1102
  return lodash.merge(
1124
1103
  {
@@ -1147,4 +1126,4 @@ exports.readMicrosoftGraphConfig = readMicrosoftGraphConfig;
1147
1126
  exports.readMicrosoftGraphOrg = readMicrosoftGraphOrg;
1148
1127
  exports.readProviderConfig = readProviderConfig;
1149
1128
  exports.readProviderConfigs = readProviderConfigs;
1150
- //# sourceMappingURL=MicrosoftGraphOrgEntityProvider-DZcLVfiM.cjs.js.map
1129
+ //# sourceMappingURL=MicrosoftGraphOrgEntityProvider-Cyc0qWct.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MicrosoftGraphOrgEntityProvider-DZcLVfiM.cjs.js","sources":["../../src/microsoftGraph/client.ts","../../src/microsoftGraph/config.ts","../../src/microsoftGraph/constants.ts","../../src/microsoftGraph/helper.ts","../../src/microsoftGraph/defaultTransformers.ts","../../src/microsoftGraph/org.ts","../../src/microsoftGraph/read.ts","../../src/processors/MicrosoftGraphOrgEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n TokenCredential,\n DefaultAzureCredential,\n ClientSecretCredential,\n} from '@azure/identity';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport fetch, { Response } from 'node-fetch';\nimport qs from 'qs';\nimport { MicrosoftGraphProviderConfig } from './config';\n\n/**\n * OData (Open Data Protocol) Query\n *\n * {@link https://docs.microsoft.com/en-us/odata/concepts/queryoptions-overview}\n * {@link https://docs.microsoft.com/en-us/graph/query-parameters}\n * @public\n */\nexport type ODataQuery = {\n /**\n * search resources within a collection matching a free-text search expression.\n */\n search?: string;\n /**\n * filter a collection of resources\n */\n filter?: string;\n /**\n * specifies the related resources or media streams to be included in line with retrieved resources\n */\n expand?: string;\n /**\n * request a specific set of properties for each entity or complex type\n */\n select?: string[];\n /**\n * Retrieves the total count of matching resources.\n */\n count?: boolean;\n /**\n * Maximum number of records to receive in one batch.\n */\n top?: number;\n};\n\n/**\n * Extends the base msgraph types to include the odata type.\n *\n * @public\n */\nexport type GroupMember =\n | (MicrosoftGraph.Group & { '@odata.type': '#microsoft.graph.user' })\n | (MicrosoftGraph.User & { '@odata.type': '#microsoft.graph.group' });\n\n/**\n * A HTTP Client that communicates with Microsoft Graph API.\n * Simplify Authentication and API calls to get `User` and `Group` from Microsoft Graph\n *\n * Uses `msal-node` for authentication\n *\n * @public\n */\nexport class MicrosoftGraphClient {\n /**\n * Factory method that instantiate `msal` client and return\n * an instance of `MicrosoftGraphClient`\n *\n * @public\n *\n * @param config - Configuration for Interacting with Graph API\n */\n static create(config: MicrosoftGraphProviderConfig): MicrosoftGraphClient {\n const options = {\n authorityHost: config.authority,\n tenantId: config.tenantId,\n };\n\n const credential =\n config.clientId && config.clientSecret\n ? new ClientSecretCredential(\n config.tenantId,\n config.clientId,\n config.clientSecret,\n options,\n )\n : new DefaultAzureCredential(options);\n\n return new MicrosoftGraphClient(config.target, credential);\n }\n\n /**\n * @param baseUrl - baseUrl of Graph API {@link MicrosoftGraphProviderConfig.target}\n * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls\n *\n */\n constructor(\n private readonly baseUrl: string,\n private readonly tokenCredential: TokenCredential,\n ) {}\n\n /**\n * Get a collection of resource from Graph API and\n * return an `AsyncIterable` of that resource\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *requestCollection<T>(\n path: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<T> {\n // upgrade to advanced query mode transparently when \"search\" is used\n // to stay backwards compatible.\n const appliedQueryMode = query?.search ? 'advanced' : queryMode ?? 'basic';\n\n // not needed for \"search\"\n // as of https://docs.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http\n // even though a few other places say the opposite\n // - https://docs.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http#request-headers\n // - https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties\n if (appliedQueryMode === 'advanced' && (query?.filter || query?.select)) {\n query.count = true;\n }\n const headers: Record<string, string> =\n appliedQueryMode === 'advanced'\n ? {\n // Eventual consistency is required for advanced querying capabilities\n // like \"$search\" or parts of \"$filter\".\n // If a new user/group is not found, it'll eventually be imported on a subsequent read\n ConsistencyLevel: 'eventual',\n }\n : {};\n\n let response = await this.requestApi(path, query, headers);\n\n for (;;) {\n if (response.status !== 200) {\n await this.handleError(path, response);\n }\n\n const result = await response.json();\n\n // Graph API return array of collections\n const elements: T[] = result.value;\n\n yield* elements;\n\n // Follow cursor to the next page if one is available\n if (!result['@odata.nextLink']) {\n return;\n }\n\n response = await this.requestRaw(result['@odata.nextLink'], headers);\n }\n }\n\n /**\n * Abstract on top of {@link MicrosoftGraphClient.requestRaw}\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param headers - optional HTTP headers\n */\n async requestApi(\n path: string,\n query?: ODataQuery,\n headers?: Record<string, string>,\n ): Promise<Response> {\n const queryString = qs.stringify(\n {\n $search: query?.search,\n $filter: query?.filter,\n $select: query?.select?.join(','),\n $expand: query?.expand,\n $count: query?.count,\n $top: query?.top,\n },\n {\n addQueryPrefix: true,\n // Microsoft Graph doesn't like an encoded query string\n encode: false,\n },\n );\n\n return await this.requestRaw(\n `${this.baseUrl}/${path}${queryString}`,\n headers,\n );\n }\n\n /**\n * Makes a HTTP call to Graph API with token\n *\n * @param url - HTTP Endpoint of Graph API\n * @param headers - optional HTTP headers\n */\n async requestRaw(\n url: string,\n headers?: Record<string, string>,\n retryCount = 2,\n ): Promise<Response> {\n // Make sure that we always have a valid access token (might be cached)\n const urlObj = new URL(url);\n const token = await this.tokenCredential.getToken(\n `${urlObj.protocol}//${urlObj.hostname}/.default`,\n );\n\n if (!token) {\n throw new Error('Failed to obtain token from Azure Identity');\n }\n\n try {\n return await fetch(url, {\n headers: {\n ...headers,\n Authorization: `Bearer ${token.token}`,\n },\n });\n } catch (e: any) {\n if (e?.code === 'ETIMEDOUT' && retryCount > 0) {\n return this.requestRaw(url, headers, retryCount - 1);\n }\n throw e;\n }\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `User` from Graph API with size limit\n *\n * @param userId - The unique identifier for the `User` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getUserPhotoWithSizeLimit(\n userId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('users', userId, maxSize);\n }\n\n async getUserPhoto(\n userId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('users', userId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getUsers(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(\n `users`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `Group` from Graph API with size limit\n *\n * @param groupId - The unique identifier for the `Group` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getGroupPhotoWithSizeLimit(\n groupId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('groups', groupId, maxSize);\n }\n\n async getGroupPhoto(\n groupId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('groups', groupId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/group | Group}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getGroups(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.Group> {\n yield* this.requestCollection<MicrosoftGraph.Group>(\n `groups`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n *\n */\n async *getGroupMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<GroupMember> {\n yield* this.requestCollection<GroupMember>(\n `groups/${groupId}/members`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getGroupUserMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(\n `groups/${groupId}/members/microsoft.graph.user/`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/organization | Organization}\n * from Graph API\n * @public\n * @param tenantId - The unique identifier for the `Organization` resource\n *\n */\n async getOrganization(\n tenantId: string,\n ): Promise<MicrosoftGraph.Organization> {\n const response = await this.requestApi(`organization/${tenantId}`);\n\n if (response.status !== 200) {\n await this.handleError(`organization/${tenantId}`, response);\n }\n\n return await response.json();\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * from Graph API\n *\n * @param entityName - type of parent resource, either `User` or `Group`\n * @param id - The unique identifier for the {@link entityName | entityName} resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n private async getPhotoWithSizeLimit(\n entityName: string,\n id: string,\n maxSize: number,\n ): Promise<string | undefined> {\n const response = await this.requestApi(`${entityName}/${id}/photos`);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError(`${entityName} photos`, response);\n }\n\n const result = await response.json();\n const photos = result.value as MicrosoftGraph.ProfilePhoto[];\n let selectedPhoto: MicrosoftGraph.ProfilePhoto | undefined = undefined;\n\n // Find the biggest picture that is smaller than the max size\n for (const p of photos) {\n if (\n !selectedPhoto ||\n (p.height! >= selectedPhoto.height! && p.height! <= maxSize)\n ) {\n selectedPhoto = p;\n }\n }\n\n if (!selectedPhoto) {\n return undefined;\n }\n\n return await this.getPhoto(entityName, id, selectedPhoto.id!);\n }\n\n private async getPhoto(\n entityName: string,\n id: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n const path = sizeId\n ? `${entityName}/${id}/photos/${sizeId}/$value`\n : `${entityName}/${id}/photo/$value`;\n const response = await this.requestApi(path);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError('photo', response);\n }\n\n return `data:image/jpeg;base64,${Buffer.from(\n await response.arrayBuffer(),\n ).toString('base64')}`;\n }\n\n private async handleError(path: string, response: Response): Promise<void> {\n const result = await response.json();\n const error = result.error as MicrosoftGraph.PublicError;\n\n throw new Error(\n `Error while reading ${path} from Microsoft Graph: ${error.code} - ${error.message}`,\n );\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n readTaskScheduleDefinitionFromConfig,\n TaskScheduleDefinition,\n} from '@backstage/backend-tasks';\nimport { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\n\nconst DEFAULT_PROVIDER_ID = 'default';\nconst DEFAULT_TARGET = 'https://graph.microsoft.com/v1.0';\n\n/**\n * The configuration parameters for a single Microsoft Graph provider.\n *\n * @public\n */\nexport type MicrosoftGraphProviderConfig = {\n /**\n * Identifier of the provider which will be used i.e. at the location key for ingested entities.\n */\n id: string;\n\n /**\n * The prefix of the target that this matches on, e.g.\n * \"https://graph.microsoft.com/v1.0\", with no trailing slash.\n */\n target: string;\n /**\n * The auth authority used.\n *\n * E.g. \"https://login.microsoftonline.com\"\n */\n authority?: string;\n /**\n * The tenant whose org data we are interested in.\n */\n tenantId: string;\n /**\n * The OAuth client ID to use for authenticating requests.\n * If specified, ClientSecret must also be specified\n */\n clientId?: string;\n /**\n * The OAuth client secret to use for authenticating requests.\n * If specified, ClientId must also be specified\n */\n clientSecret?: string;\n /**\n * The filter to apply to extract users.\n *\n * E.g. \"accountEnabled eq true and userType eq 'member'\"\n */\n userFilter?: string;\n /**\n * The fields to be fetched on query.\n *\n * E.g. [\"id\", \"displayName\", \"description\"]\n */\n userSelect?: string[];\n /**\n * The \"expand\" argument to apply to users.\n *\n * E.g. \"manager\".\n */\n userExpand?: string;\n /**\n * The filter to apply to extract users by groups memberships.\n *\n * E.g. \"displayName eq 'Backstage Users'\"\n */\n userGroupMemberFilter?: string;\n /**\n * The search criteria to apply to extract users by groups memberships.\n *\n * E.g. \"\\\"displayName:-team\\\"\" would only match groups which contain '-team'\n */\n userGroupMemberSearch?: string;\n /**\n * The \"expand\" argument to apply to groups.\n *\n * E.g. \"member\".\n */\n groupExpand?: string;\n /**\n * The filter to apply to extract groups.\n *\n * E.g. \"securityEnabled eq false and mailEnabled eq true\"\n */\n groupFilter?: string;\n /**\n * The search criteria to apply to extract groups.\n *\n * E.g. \"\\\"displayName:-team\\\"\" would only match groups which contain '-team'\n */\n groupSearch?: string;\n\n /**\n * The fields to be fetched on query.\n *\n * E.g. [\"id\", \"displayName\", \"description\"]\n */\n groupSelect?: string[];\n\n /**\n * By default, the Microsoft Graph API only provides the basic feature set\n * for querying. Certain features are limited to advanced query capabilities\n * (see https://docs.microsoft.com/en-us/graph/aad-advanced-queries)\n * and need to be enabled.\n *\n * Some features like `$expand` are not available for advanced queries, though.\n */\n queryMode?: 'basic' | 'advanced';\n\n /**\n * Set to false to not load user photos.\n * This can be useful for huge organizations.\n */\n loadUserPhotos?: boolean;\n\n /**\n * Schedule configuration for refresh tasks.\n */\n schedule?: TaskScheduleDefinition;\n};\n\n/**\n * Parses configuration.\n *\n * @param config - The root of the msgraph config hierarchy\n *\n * @public\n * @deprecated Replaced by not exported `readProviderConfigs` and kept for backwards compatibility only.\n */\nexport function readMicrosoftGraphConfig(\n config: Config,\n): MicrosoftGraphProviderConfig[] {\n const providers: MicrosoftGraphProviderConfig[] = [];\n const providerConfigs = config.getOptionalConfigArray('providers') ?? [];\n\n for (const providerConfig of providerConfigs) {\n const target = trimEnd(\n providerConfig.getOptionalString('target') ?? DEFAULT_TARGET,\n '/',\n );\n const authority = providerConfig.getOptionalString('authority');\n\n const tenantId = providerConfig.getString('tenantId');\n const clientId = providerConfig.getOptionalString('clientId');\n const clientSecret = providerConfig.getOptionalString('clientSecret');\n\n const userExpand = providerConfig.getOptionalString('userExpand');\n const userFilter = providerConfig.getOptionalString('userFilter');\n const userSelect = providerConfig.getOptionalStringArray('userSelect');\n const userGroupMemberFilter = providerConfig.getOptionalString(\n 'userGroupMemberFilter',\n );\n const userGroupMemberSearch = providerConfig.getOptionalString(\n 'userGroupMemberSearch',\n );\n const groupExpand = providerConfig.getOptionalString('groupExpand');\n const groupFilter = providerConfig.getOptionalString('groupFilter');\n const groupSearch = providerConfig.getOptionalString('groupSearch');\n\n if (userFilter && userGroupMemberFilter) {\n throw new Error(\n `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,\n );\n }\n if (userFilter && userGroupMemberSearch) {\n throw new Error(\n `userGroupMemberSearch cannot be specified when userFilter is defined.`,\n );\n }\n\n const groupSelect = providerConfig.getOptionalStringArray('groupSelect');\n const queryMode = providerConfig.getOptionalString('queryMode');\n if (\n queryMode !== undefined &&\n queryMode !== 'basic' &&\n queryMode !== 'advanced'\n ) {\n throw new Error(`queryMode must be one of: basic, advanced`);\n }\n\n if (clientId && !clientSecret) {\n throw new Error(\n `clientSecret must be provided when clientId is defined.`,\n );\n }\n\n if (clientSecret && !clientId) {\n throw new Error(\n `clientId must be provided when clientSecret is defined.`,\n );\n }\n\n providers.push({\n id: target,\n target,\n authority,\n tenantId,\n clientId,\n clientSecret,\n userExpand,\n userFilter,\n userSelect,\n userGroupMemberFilter,\n userGroupMemberSearch,\n groupExpand,\n groupFilter,\n groupSearch,\n groupSelect,\n queryMode,\n });\n }\n\n return providers;\n}\n\n/**\n * Parses all configured providers.\n *\n * @param config - The root of the msgraph config hierarchy\n *\n * @public\n */\nexport function readProviderConfigs(\n config: Config,\n): MicrosoftGraphProviderConfig[] {\n const providersConfig = config.getOptionalConfig(\n 'catalog.providers.microsoftGraphOrg',\n );\n if (!providersConfig) {\n return [];\n }\n\n if (providersConfig.has('clientId')) {\n // simple/single config variant\n return [readProviderConfig(DEFAULT_PROVIDER_ID, providersConfig)];\n }\n\n return providersConfig.keys().map(id => {\n const providerConfig = providersConfig.getConfig(id);\n\n return readProviderConfig(id, providerConfig);\n });\n}\n\n/**\n * Parses a single configured provider by id.\n *\n * @param id - the id of the provider to parse\n * @param config - The root of the msgraph config hierarchy\n *\n * @public\n */\nexport function readProviderConfig(\n id: string,\n config: Config,\n): MicrosoftGraphProviderConfig {\n const target = trimEnd(\n config.getOptionalString('target') ?? DEFAULT_TARGET,\n '/',\n );\n const authority = config.getOptionalString('authority');\n\n const tenantId = config.getString('tenantId');\n const clientId = config.getOptionalString('clientId');\n const clientSecret = config.getOptionalString('clientSecret');\n\n const userExpand = config.getOptionalString('user.expand');\n const userFilter = config.getOptionalString('user.filter');\n const userSelect = config.getOptionalStringArray('user.select');\n const loadUserPhotos = config.getOptionalBoolean('user.loadPhotos');\n\n const groupExpand = config.getOptionalString('group.expand');\n const groupFilter = config.getOptionalString('group.filter');\n const groupSearch = config.getOptionalString('group.search');\n const groupSelect = config.getOptionalStringArray('group.select');\n\n const queryMode = config.getOptionalString('queryMode');\n if (\n queryMode !== undefined &&\n queryMode !== 'basic' &&\n queryMode !== 'advanced'\n ) {\n throw new Error(`queryMode must be one of: basic, advanced`);\n }\n\n const userGroupMemberFilter = config.getOptionalString(\n 'userGroupMember.filter',\n );\n const userGroupMemberSearch = config.getOptionalString(\n 'userGroupMember.search',\n );\n\n if (userFilter && userGroupMemberFilter) {\n throw new Error(\n `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,\n );\n }\n if (userFilter && userGroupMemberSearch) {\n throw new Error(\n `userGroupMemberSearch cannot be specified when userFilter is defined.`,\n );\n }\n\n if (clientId && !clientSecret) {\n throw new Error(`clientSecret must be provided when clientId is defined.`);\n }\n\n if (clientSecret && !clientId) {\n throw new Error(`clientId must be provided when clientSecret is defined.`);\n }\n\n const schedule = config.has('schedule')\n ? readTaskScheduleDefinitionFromConfig(config.getConfig('schedule'))\n : undefined;\n\n return {\n id,\n target,\n authority,\n clientId,\n clientSecret,\n tenantId,\n userExpand,\n userFilter,\n userSelect,\n loadUserPhotos,\n groupExpand,\n groupFilter,\n groupSearch,\n groupSelect,\n queryMode,\n userGroupMemberFilter,\n userGroupMemberSearch,\n schedule,\n };\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The (primary) user email. Also used by the Microsoft auth provider to resolve the User entity.\n *\n * @public\n */\nexport const MICROSOFT_EMAIL_ANNOTATION = 'microsoft.com/email';\n\n/**\n * The tenant id used by the Microsoft Graph API\n *\n * @public\n */\nexport const MICROSOFT_GRAPH_TENANT_ID_ANNOTATION =\n 'graph.microsoft.com/tenant-id';\n\n/**\n * The group id used by the Microsoft Graph API\n *\n * @public\n */\nexport const MICROSOFT_GRAPH_GROUP_ID_ANNOTATION =\n 'graph.microsoft.com/group-id';\n\n/**\n * The user id used by the Microsoft Graph API\n *\n * @public\n */\nexport const MICROSOFT_GRAPH_USER_ID_ANNOTATION = 'graph.microsoft.com/user-id';\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Takes an input string and cleans it up to become suitable as an entity name.\n *\n * @public\n */\nexport function normalizeEntityName(name: string): string {\n let cleaned = name\n .trim()\n .toLocaleLowerCase()\n .replace(/[^a-zA-Z0-9_\\-\\.]/g, '_');\n\n // invalid to end with _\n while (cleaned.endsWith('_')) {\n cleaned = cleaned.substring(0, cleaned.length - 1);\n }\n\n // cleans up format for groups like 'my group (Reader)'\n while (cleaned.includes('__')) {\n // replaceAll from node.js >= 15\n cleaned = cleaned.replace('__', '_');\n }\n\n return cleaned;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n MICROSOFT_EMAIL_ANNOTATION,\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n} from './constants';\nimport { normalizeEntityName } from './helper';\nimport { GroupEntity, UserEntity } from '@backstage/catalog-model';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\n\n/**\n * The default implementation of the transformation from a graph organization\n * entry to a Group entity.\n *\n * @public\n */\nexport async function defaultOrganizationTransformer(\n organization: MicrosoftGraph.Organization,\n): Promise<GroupEntity | undefined> {\n if (!organization.id || !organization.displayName) {\n return undefined;\n }\n\n const name = normalizeEntityName(organization.displayName!);\n return {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Group',\n metadata: {\n name: name,\n description: organization.displayName!,\n annotations: {\n [MICROSOFT_GRAPH_TENANT_ID_ANNOTATION]: organization.id!,\n },\n },\n spec: {\n type: 'root',\n profile: {\n displayName: organization.displayName!,\n },\n children: [],\n },\n };\n}\n\nfunction extractGroupName(group: MicrosoftGraph.Group): string {\n if (group.securityEnabled) {\n return group.displayName as string;\n }\n return (group.mailNickname || group.displayName) as string;\n}\n\n/**\n * The default implementation of the transformation from a graph group entry to\n * a Group entity.\n *\n * @public\n */\nexport async function defaultGroupTransformer(\n group: MicrosoftGraph.Group,\n groupPhoto?: string,\n): Promise<GroupEntity | undefined> {\n if (!group.id || !group.displayName) {\n return undefined;\n }\n\n const name = normalizeEntityName(extractGroupName(group));\n const entity: GroupEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Group',\n metadata: {\n name: name,\n annotations: {\n [MICROSOFT_GRAPH_GROUP_ID_ANNOTATION]: group.id,\n },\n },\n spec: {\n type: 'team',\n profile: {},\n children: [],\n },\n };\n\n if (group.description) {\n entity.metadata.description = group.description;\n }\n if (group.displayName) {\n entity.spec.profile!.displayName = group.displayName;\n }\n if (group.mail) {\n entity.spec.profile!.email = group.mail;\n }\n if (groupPhoto) {\n entity.spec.profile!.picture = groupPhoto;\n }\n\n return entity;\n}\n\n/**\n * The default implementation of the transformation from a graph user entry to\n * a User entity.\n *\n * @public\n */\nexport async function defaultUserTransformer(\n user: MicrosoftGraph.User,\n userPhoto?: string,\n): Promise<UserEntity | undefined> {\n if (!user.id || !user.displayName || !user.mail) {\n return undefined;\n }\n\n const name = normalizeEntityName(user.mail);\n const entity: UserEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'User',\n metadata: {\n name,\n annotations: {\n [MICROSOFT_EMAIL_ANNOTATION]: user.mail!,\n [MICROSOFT_GRAPH_USER_ID_ANNOTATION]: user.id!,\n },\n },\n spec: {\n profile: {\n displayName: user.displayName!,\n email: user.mail!,\n\n // TODO: Additional fields?\n // jobTitle: user.jobTitle || undefined,\n // officeLocation: user.officeLocation || undefined,\n // mobilePhone: user.mobilePhone || undefined,\n },\n memberOf: [],\n },\n };\n\n if (userPhoto) {\n entity.spec.profile!.picture = userPhoto;\n }\n\n return entity;\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GroupEntity, UserEntity } from '@backstage/catalog-model';\n\n// TODO: Copied from plugin-catalog-backend, but we could also export them from\n// there. Or move them to catalog-model.\n\nexport function buildOrgHierarchy(groups: GroupEntity[]) {\n const groupsByName = new Map(groups.map(g => [g.metadata.name, g]));\n\n //\n // Make sure that g.parent.children contain g\n //\n\n for (const group of groups) {\n const selfName = group.metadata.name;\n const parentName = group.spec.parent;\n if (parentName) {\n const parent = groupsByName.get(parentName);\n if (parent && !parent.spec.children.includes(selfName)) {\n parent.spec.children.push(selfName);\n }\n }\n }\n\n //\n // Make sure that g.children.parent is g\n //\n\n for (const group of groups) {\n const selfName = group.metadata.name;\n for (const childName of group.spec.children) {\n const child = groupsByName.get(childName);\n if (child && !child.spec.parent) {\n child.spec.parent = selfName;\n }\n }\n }\n}\n\n// Ensure that users have their transitive group memberships. Requires that\n// the groups were previously processed with buildOrgHierarchy()\nexport function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) {\n const groupsByName = new Map(groups.map(g => [g.metadata.name, g]));\n\n users.forEach(user => {\n const transitiveMemberOf = new Set<string>();\n\n const todo = [\n ...(user.spec.memberOf ?? []),\n ...groups\n .filter(g => g.spec.members?.includes(user.metadata.name))\n .map(g => g.metadata.name),\n ];\n\n for (;;) {\n const current = todo.pop();\n if (!current) {\n break;\n }\n\n if (!transitiveMemberOf.has(current)) {\n transitiveMemberOf.add(current);\n const group = groupsByName.get(current);\n if (group?.spec.parent) {\n todo.push(group.spec.parent);\n }\n }\n }\n\n user.spec.memberOf = [...transitiveMemberOf];\n });\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n GroupEntity,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport limiterFactory from 'p-limit';\nimport { MicrosoftGraphClient } from './client';\nimport {\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n} from './constants';\nimport { buildMemberOf, buildOrgHierarchy } from './org';\nimport {\n GroupTransformer,\n OrganizationTransformer,\n UserTransformer,\n} from './types';\nimport {\n defaultGroupTransformer,\n defaultOrganizationTransformer,\n defaultUserTransformer,\n} from './defaultTransformers';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst PAGE_SIZE = 999;\n\nexport async function readMicrosoftGraphUsers(\n client: MicrosoftGraphClient,\n options: {\n queryMode?: 'basic' | 'advanced';\n userExpand?: string;\n userFilter?: string;\n userSelect?: string[];\n loadUserPhotos?: boolean;\n transformer?: UserTransformer;\n logger: LoggerService;\n },\n): Promise<{\n users: UserEntity[]; // With all relations empty\n}> {\n const users = client.getUsers(\n {\n filter: options.userFilter,\n expand: options.userExpand,\n select: options.userSelect,\n top: PAGE_SIZE,\n },\n options.queryMode,\n );\n\n return {\n users: await transformUsers(\n client,\n users,\n options.logger,\n options.loadUserPhotos,\n options.transformer,\n ),\n };\n}\n\nexport async function readMicrosoftGraphUsersInGroups(\n client: MicrosoftGraphClient,\n options: {\n queryMode?: 'basic' | 'advanced';\n userExpand?: string;\n userFilter?: string;\n userSelect?: string[];\n loadUserPhotos?: boolean;\n userGroupMemberSearch?: string;\n userGroupMemberFilter?: string;\n groupExpand?: string;\n transformer?: UserTransformer;\n logger: LoggerService;\n },\n): Promise<{\n users: UserEntity[]; // With all relations empty\n}> {\n const limiter = limiterFactory(10);\n\n const userGroupMemberPromises: Promise<void>[] = [];\n const userGroupMembers = new Map<string, MicrosoftGraph.User>();\n\n for await (const group of client.getGroups(\n {\n expand: options.groupExpand,\n filter: options.userGroupMemberFilter,\n search: options.userGroupMemberSearch,\n select: ['id', 'displayName'],\n top: PAGE_SIZE,\n },\n options.queryMode,\n )) {\n // Process all groups in parallel, otherwise it can take quite some time\n userGroupMemberPromises.push(\n limiter(async () => {\n let groupMemberCount = 0;\n for await (const user of client.getGroupUserMembers(\n group.id!,\n {\n expand: options.userExpand,\n filter: options.userFilter,\n select: options.userSelect,\n top: PAGE_SIZE,\n },\n options.queryMode,\n )) {\n userGroupMembers.set(user.id!, user);\n groupMemberCount++;\n }\n options.logger.debug('Read users from group', {\n groupId: group.id,\n groupName: group.displayName,\n memberCount: groupMemberCount,\n });\n }),\n );\n }\n\n // Wait for all group members\n await Promise.all(userGroupMemberPromises);\n\n options.logger.info('Read users from group membership', {\n groupCount: userGroupMemberPromises.length,\n userCount: userGroupMembers.size,\n });\n\n return {\n users: await transformUsers(\n client,\n userGroupMembers.values(),\n options.logger,\n options.loadUserPhotos,\n options.transformer,\n ),\n };\n}\n\nexport async function readMicrosoftGraphOrganization(\n client: MicrosoftGraphClient,\n tenantId: string,\n options?: { transformer?: OrganizationTransformer },\n): Promise<{\n rootGroup?: GroupEntity; // With all relations empty\n}> {\n // For now we expect a single root organization\n const organization = await client.getOrganization(tenantId);\n const transformer = options?.transformer ?? defaultOrganizationTransformer;\n const rootGroup = await transformer(organization);\n\n return { rootGroup };\n}\n\nexport async function readMicrosoftGraphGroups(\n client: MicrosoftGraphClient,\n tenantId: string,\n options?: {\n queryMode?: 'basic' | 'advanced';\n groupExpand?: string;\n groupFilter?: string;\n groupSearch?: string;\n groupSelect?: string[];\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n },\n): Promise<{\n groups: GroupEntity[]; // With all relations empty\n rootGroup: GroupEntity | undefined; // With all relations empty\n groupMember: Map<string, Set<string>>;\n groupMemberOf: Map<string, Set<string>>;\n}> {\n const groups: GroupEntity[] = [];\n const groupMember: Map<string, Set<string>> = new Map();\n const groupMemberOf: Map<string, Set<string>> = new Map();\n const limiter = limiterFactory(10);\n\n const { rootGroup } = await readMicrosoftGraphOrganization(client, tenantId, {\n transformer: options?.organizationTransformer,\n });\n if (rootGroup) {\n groupMember.set(rootGroup.metadata.name, new Set<string>());\n groups.push(rootGroup);\n }\n\n const transformer = options?.groupTransformer ?? defaultGroupTransformer;\n const promises: Promise<void>[] = [];\n\n for await (const group of client.getGroups(\n {\n expand: options?.groupExpand,\n filter: options?.groupFilter,\n search: options?.groupSearch,\n select: options?.groupSelect,\n top: PAGE_SIZE,\n },\n options?.queryMode,\n )) {\n // Process all groups in parallel, otherwise it can take quite some time\n promises.push(\n limiter(async () => {\n // TODO: Loading groups photos doesn't work right now as Microsoft Graph\n // doesn't allows this yet: https://microsoftgraph.uservoice.com/forums/920506-microsoft-graph-feature-requests/suggestions/37884922-allow-application-to-set-or-update-a-group-s-photo\n /* const groupPhoto = await client.getGroupPhotoWithSizeLimit(\n group.id!,\n // We are limiting the photo size, as groups with full resolution photos\n // can make the Backstage API slow\n 120,\n );*/\n\n const entity = await transformer(group /* , groupPhoto*/);\n\n if (!entity) {\n return;\n }\n\n for await (const member of client.getGroupMembers(group.id!, {\n top: PAGE_SIZE,\n })) {\n if (!member.id) {\n continue;\n }\n\n if (member['@odata.type'] === '#microsoft.graph.user') {\n ensureItem(groupMemberOf, member.id, group.id!);\n }\n\n if (member['@odata.type'] === '#microsoft.graph.group') {\n ensureItem(groupMember, group.id!, member.id);\n }\n }\n\n groups.push(entity);\n }),\n );\n }\n\n // Wait for all group members and photos to be loaded\n await Promise.all(promises);\n\n return {\n groups,\n rootGroup,\n groupMember,\n groupMemberOf,\n };\n}\n\nexport function resolveRelations(\n rootGroup: GroupEntity | undefined,\n groups: GroupEntity[],\n users: UserEntity[],\n groupMember: Map<string, Set<string>>,\n groupMemberOf: Map<string, Set<string>>,\n) {\n // Build reference lookup tables, we reference them by the id the the graph\n const groupMap: Map<string, GroupEntity> = new Map(); // by group-id or tenant-id\n\n for (const group of groups) {\n if (group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION]) {\n groupMap.set(\n group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION],\n group,\n );\n }\n if (group.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION]) {\n groupMap.set(\n group.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION],\n group,\n );\n }\n }\n\n // Resolve all member relationships into the reverse direction\n const parentGroups = new Map<string, Set<string>>();\n\n groupMember.forEach((members, groupId) =>\n members.forEach(m => ensureItem(parentGroups, m, groupId)),\n );\n\n // Make sure every group (except root) has at least one parent. If the parent is missing, add the root.\n if (rootGroup) {\n const tenantId =\n rootGroup.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];\n\n groups.forEach(group => {\n const groupId =\n group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION];\n\n if (!groupId) {\n return;\n }\n\n if (retrieveItems(parentGroups, groupId).size === 0) {\n ensureItem(parentGroups, groupId, tenantId);\n ensureItem(groupMember, tenantId, groupId);\n }\n });\n }\n\n groups.forEach(group => {\n const id =\n group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ??\n group.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];\n\n retrieveItems(groupMember, id).forEach(m => {\n const childGroup = groupMap.get(m);\n if (childGroup) {\n group.spec.children.push(stringifyEntityRef(childGroup));\n }\n });\n\n retrieveItems(parentGroups, id).forEach(p => {\n const parentGroup = groupMap.get(p);\n if (parentGroup) {\n // TODO: Only having a single parent group might not match every companies model, but fine for now.\n group.spec.parent = stringifyEntityRef(parentGroup);\n }\n });\n });\n\n // Make sure that all groups have proper parents and children\n buildOrgHierarchy(groups);\n\n // Set relations for all users\n users.forEach(user => {\n const id = user.metadata.annotations![MICROSOFT_GRAPH_USER_ID_ANNOTATION];\n\n retrieveItems(groupMemberOf, id).forEach(p => {\n const parentGroup = groupMap.get(p);\n if (parentGroup) {\n if (!user.spec.memberOf) {\n user.spec.memberOf = [];\n }\n user.spec.memberOf.push(stringifyEntityRef(parentGroup));\n }\n });\n });\n\n // Make sure all transitive memberships are available\n buildMemberOf(groups, users);\n}\n\n/**\n * Reads an entire org as Group and User entities.\n *\n * @public\n */\nexport async function readMicrosoftGraphOrg(\n client: MicrosoftGraphClient,\n tenantId: string,\n options: {\n userExpand?: string;\n userFilter?: string;\n userSelect?: string[];\n loadUserPhotos?: boolean;\n userGroupMemberSearch?: string;\n userGroupMemberFilter?: string;\n groupExpand?: string;\n groupSearch?: string;\n groupFilter?: string;\n groupSelect?: string[];\n queryMode?: 'basic' | 'advanced';\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n logger: LoggerService;\n },\n): Promise<{ users: UserEntity[]; groups: GroupEntity[] }> {\n let users: UserEntity[] = [];\n\n if (options.userGroupMemberFilter || options.userGroupMemberSearch) {\n const { users: usersInGroups } = await readMicrosoftGraphUsersInGroups(\n client,\n {\n queryMode: options.queryMode,\n userExpand: options.userExpand,\n userFilter: options.userFilter,\n userSelect: options.userSelect,\n userGroupMemberFilter: options.userGroupMemberFilter,\n userGroupMemberSearch: options.userGroupMemberSearch,\n loadUserPhotos: options.loadUserPhotos,\n transformer: options.userTransformer,\n logger: options.logger,\n },\n );\n users = usersInGroups;\n } else {\n const { users: usersWithFilter } = await readMicrosoftGraphUsers(client, {\n queryMode: options.queryMode,\n userExpand: options.userExpand,\n userFilter: options.userFilter,\n userSelect: options.userSelect,\n loadUserPhotos: options.loadUserPhotos,\n transformer: options.userTransformer,\n logger: options.logger,\n });\n users = usersWithFilter;\n }\n const { groups, rootGroup, groupMember, groupMemberOf } =\n await readMicrosoftGraphGroups(client, tenantId, {\n queryMode: options.queryMode,\n groupExpand: options.groupExpand,\n groupFilter: options.groupFilter,\n groupSearch: options.groupSearch,\n groupSelect: options.groupSelect,\n groupTransformer: options.groupTransformer,\n organizationTransformer: options.organizationTransformer,\n });\n\n resolveRelations(rootGroup, groups, users, groupMember, groupMemberOf);\n users.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));\n groups.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));\n\n return { users, groups };\n}\n\nasync function transformUsers(\n client: MicrosoftGraphClient,\n users: Iterable<MicrosoftGraph.User> | AsyncIterable<MicrosoftGraph.User>,\n logger: LoggerService,\n loadUserPhotos = true,\n transformer?: UserTransformer,\n) {\n const limiter = limiterFactory(10);\n\n const resolvedTransformer = transformer ?? defaultUserTransformer;\n const promises: Promise<void>[] = [];\n const entities: UserEntity[] = [];\n\n // Process all users in parallel, otherwise it can take quite some time\n for await (const user of users) {\n promises.push(\n limiter(async () => {\n let userPhoto;\n try {\n if (loadUserPhotos) {\n userPhoto = await client.getUserPhotoWithSizeLimit(\n user.id!,\n // We are limiting the photo size, as users with full resolution photos\n // can make the Backstage API slow\n 120,\n );\n }\n } catch (e) {\n logger.warn(`Unable to load user photo for`, {\n user: user.id,\n error: e,\n });\n }\n\n const entity = await resolvedTransformer(user, userPhoto);\n\n if (entity) {\n entities.push(entity);\n }\n }),\n );\n }\n\n // Wait for all users and photos to be downloaded\n await Promise.all(promises);\n\n logger.debug('Finished transforming users', {\n microsoftUserCount: promises.length,\n backstageUserCount: entities.length,\n });\n return entities;\n}\n\nfunction ensureItem(\n target: Map<string, Set<string>>,\n key: string,\n value: string,\n) {\n let set = target.get(key);\n if (!set) {\n set = new Set();\n target.set(key, set);\n }\n set!.add(value);\n}\n\nfunction retrieveItems(\n target: Map<string, Set<string>>,\n key: string,\n): Set<string> {\n return target.get(key) ?? new Set();\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';\nimport {\n ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n Entity,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\nimport { merge } from 'lodash';\nimport * as uuid from 'uuid';\nimport {\n GroupTransformer,\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n MicrosoftGraphClient,\n MicrosoftGraphProviderConfig,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { readProviderConfigs } from '../microsoftGraph/config';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n/**\n * Options for {@link MicrosoftGraphOrgEntityProvider}.\n *\n * @public\n */\nexport type MicrosoftGraphOrgEntityProviderOptions =\n | MicrosoftGraphOrgEntityProviderLegacyOptions\n | {\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule?: 'manual' | TaskRunner;\n\n /**\n * Scheduler used to schedule refreshes based on\n * the schedule config.\n */\n scheduler?: PluginTaskScheduler;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n userTransformer?: UserTransformer | Record<string, UserTransformer>;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n groupTransformer?: GroupTransformer | Record<string, GroupTransformer>;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n organizationTransformer?:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>;\n };\n\n/**\n * Legacy options for {@link MicrosoftGraphOrgEntityProvider}\n * based on `catalog.processors.microsoftGraphOrg`.\n *\n * @public\n * @deprecated This interface exists for backwards compatibility only and will be removed in the future.\n */\nexport interface MicrosoftGraphOrgEntityProviderLegacyOptions {\n /**\n * A unique, stable identifier for this provider.\n *\n * @example \"production\"\n */\n id: string;\n\n /**\n * The target that this provider should consume.\n *\n * Should exactly match the \"target\" field of one of the provider\n * configuration entries.\n */\n target: string;\n\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule: 'manual' | TaskRunner;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n */\n userTransformer?: UserTransformer;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n */\n groupTransformer?: GroupTransformer;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n */\n organizationTransformer?: OrganizationTransformer;\n}\n\n/**\n * Reads user and group entries out of Microsoft Graph, and provides them as\n * User and Group entities for the catalog.\n *\n * @public\n */\nexport class MicrosoftGraphOrgEntityProvider implements EntityProvider {\n private connection?: EntityProviderConnection;\n private scheduleFn?: () => Promise<void>;\n\n static fromConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderOptions,\n ): MicrosoftGraphOrgEntityProvider[] {\n if ('id' in options) {\n return [\n MicrosoftGraphOrgEntityProvider.fromLegacyConfig(configRoot, options),\n ];\n }\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\n function getTransformer<T extends Function>(\n id: string,\n transformers?: T | Record<string, T>,\n ): T | undefined {\n if (['undefined', 'function'].includes(typeof transformers)) {\n return transformers as T;\n }\n\n return (transformers as Record<string, T>)[id];\n }\n\n return readProviderConfigs(configRoot).map(providerConfig => {\n if (!options.schedule && !providerConfig.schedule) {\n throw new Error(\n `No schedule provided neither via code nor config for MicrosoftGraphOrgEntityProvider:${providerConfig.id}.`,\n );\n }\n\n const taskRunner =\n options.schedule ??\n options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!);\n\n const provider = new MicrosoftGraphOrgEntityProvider({\n id: providerConfig.id,\n provider: providerConfig,\n logger: options.logger,\n userTransformer: getTransformer(\n providerConfig.id,\n options.userTransformer,\n ),\n groupTransformer: getTransformer(\n providerConfig.id,\n options.groupTransformer,\n ),\n organizationTransformer: getTransformer(\n providerConfig.id,\n options.organizationTransformer,\n ),\n });\n\n if (taskRunner !== 'manual') {\n provider.schedule(taskRunner);\n }\n\n return provider;\n });\n }\n\n /**\n * @deprecated Exists for backwards compatibility only and will be removed in the future.\n */\n private static fromLegacyConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderLegacyOptions,\n ): MicrosoftGraphOrgEntityProvider {\n options.logger.warn(\n 'Deprecated msgraph config \"catalog.processors.microsoftGraphOrg\" used. Use \"catalog.providers.microsoftGraphOrg\" instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1',\n );\n const config = configRoot.getOptionalConfig(\n 'catalog.processors.microsoftGraphOrg',\n );\n const providers = config ? readMicrosoftGraphConfig(config) : [];\n const provider = providers.find(p => options.target.startsWith(p.target));\n\n if (!provider) {\n throw new Error(\n `There is no Microsoft Graph Org provider that matches \"${options.target}\". Please add a configuration entry for it under \"catalog.processors.microsoftGraphOrg.providers\".`,\n );\n }\n\n const logger = options.logger.child({\n target: options.target,\n });\n\n const result = new MicrosoftGraphOrgEntityProvider({\n id: options.id,\n userTransformer: options.userTransformer,\n groupTransformer: options.groupTransformer,\n organizationTransformer: options.organizationTransformer,\n logger,\n provider,\n });\n\n if (options.schedule !== 'manual') {\n result.schedule(options.schedule);\n }\n\n return result;\n }\n\n constructor(\n private options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n },\n ) {}\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */\n getProviderName() {\n return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */\n async connect(connection: EntityProviderConnection) {\n this.connection = connection;\n await this.scheduleFn?.();\n }\n\n /**\n * Runs one complete ingestion loop. Call this method regularly at some\n * appropriate cadence.\n */\n async read(options?: { logger?: LoggerService }) {\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n\n const logger = options?.logger ?? this.options.logger;\n const provider = this.options.provider;\n const { markReadComplete } = trackProgress(logger);\n const client = MicrosoftGraphClient.create(this.options.provider);\n const { users, groups } = await readMicrosoftGraphOrg(\n client,\n provider.tenantId,\n {\n userExpand: provider.userExpand,\n userFilter: provider.userFilter,\n userSelect: provider.userSelect,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n queryMode: provider.queryMode,\n groupTransformer: this.options.groupTransformer,\n userTransformer: this.options.userTransformer,\n organizationTransformer: this.options.organizationTransformer,\n logger: logger,\n },\n );\n\n const { markCommitComplete } = markReadComplete({ users, groups });\n\n await this.connection.applyMutation({\n type: 'full',\n entities: [...users, ...groups].map(entity => ({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, entity),\n })),\n });\n\n markCommitComplete();\n }\n\n private schedule(taskRunner: TaskRunner) {\n this.scheduleFn = async () => {\n const id = `${this.getProviderName()}:refresh`;\n await taskRunner.run({\n id,\n fn: async () => {\n const logger = this.options.logger.child({\n class: MicrosoftGraphOrgEntityProvider.prototype.constructor.name,\n taskId: id,\n taskInstanceId: uuid.v4(),\n });\n\n try {\n await this.read({ logger });\n } catch (error) {\n logger.error(\n `${this.getProviderName()} refresh failed, ${error}`,\n error,\n );\n }\n },\n });\n };\n }\n}\n\n// Helps wrap the timing and logging behaviors\nfunction trackProgress(logger: LoggerService) {\n let timestamp = Date.now();\n let summary: string;\n\n logger.info('Reading msgraph users and groups');\n\n function markReadComplete(read: { users: unknown[]; groups: unknown[] }) {\n summary = `${read.users.length} msgraph users and ${read.groups.length} msgraph groups`;\n const readDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n timestamp = Date.now();\n logger.info(`Read ${summary} in ${readDuration} seconds. Committing...`);\n return { markCommitComplete };\n }\n\n function markCommitComplete() {\n const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n logger.info(`Committed ${summary} in ${commitDuration} seconds.`);\n }\n\n return { markReadComplete };\n}\n\n// Makes sure that emitted entities have a proper location based on their uuid\nexport function withLocations(providerId: string, entity: Entity): Entity {\n const uid =\n entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION] ||\n entity.metadata.name;\n const location = `msgraph:${providerId}/${encodeURIComponent(uid)}`;\n return merge(\n {\n metadata: {\n annotations: {\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n },\n },\n entity,\n ) as Entity;\n}\n"],"names":["ClientSecretCredential","DefaultAzureCredential","qs","fetch","trimEnd","readTaskScheduleDefinitionFromConfig","_a","limiterFactory","stringifyEntityRef","uuid","merge","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION"],"mappings":"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"}
1
+ {"version":3,"file":"MicrosoftGraphOrgEntityProvider-Cyc0qWct.cjs.js","sources":["../../src/microsoftGraph/client.ts","../../src/microsoftGraph/config.ts","../../src/microsoftGraph/constants.ts","../../src/microsoftGraph/helper.ts","../../src/microsoftGraph/defaultTransformers.ts","../../src/microsoftGraph/org.ts","../../src/microsoftGraph/read.ts","../../src/processors/MicrosoftGraphOrgEntityProvider.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n TokenCredential,\n DefaultAzureCredential,\n ClientSecretCredential,\n} from '@azure/identity';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport fetch, { Response } from 'node-fetch';\nimport qs from 'qs';\nimport { MicrosoftGraphProviderConfig } from './config';\n\n/**\n * OData (Open Data Protocol) Query\n *\n * {@link https://docs.microsoft.com/en-us/odata/concepts/queryoptions-overview}\n * {@link https://docs.microsoft.com/en-us/graph/query-parameters}\n * @public\n */\nexport type ODataQuery = {\n /**\n * search resources within a collection matching a free-text search expression.\n */\n search?: string;\n /**\n * filter a collection of resources\n */\n filter?: string;\n /**\n * specifies the related resources or media streams to be included in line with retrieved resources\n */\n expand?: string;\n /**\n * request a specific set of properties for each entity or complex type\n */\n select?: string[];\n /**\n * Retrieves the total count of matching resources.\n */\n count?: boolean;\n /**\n * Maximum number of records to receive in one batch.\n */\n top?: number;\n};\n\n/**\n * Extends the base msgraph types to include the odata type.\n *\n * @public\n */\nexport type GroupMember =\n | (MicrosoftGraph.Group & { '@odata.type': '#microsoft.graph.user' })\n | (MicrosoftGraph.User & { '@odata.type': '#microsoft.graph.group' });\n\n/**\n * A HTTP Client that communicates with Microsoft Graph API.\n * Simplify Authentication and API calls to get `User` and `Group` from Microsoft Graph\n *\n * Uses `msal-node` for authentication\n *\n * @public\n */\nexport class MicrosoftGraphClient {\n /**\n * Factory method that instantiate `msal` client and return\n * an instance of `MicrosoftGraphClient`\n *\n * @public\n *\n * @param config - Configuration for Interacting with Graph API\n */\n static create(config: MicrosoftGraphProviderConfig): MicrosoftGraphClient {\n const options = {\n authorityHost: config.authority,\n tenantId: config.tenantId,\n };\n\n const credential =\n config.clientId && config.clientSecret\n ? new ClientSecretCredential(\n config.tenantId,\n config.clientId,\n config.clientSecret,\n options,\n )\n : new DefaultAzureCredential(options);\n\n return new MicrosoftGraphClient(config.target, credential);\n }\n\n /**\n * @param baseUrl - baseUrl of Graph API {@link MicrosoftGraphProviderConfig.target}\n * @param tokenCredential - instance of `TokenCredential` that is used to acquire token for Graph API calls\n *\n */\n constructor(\n private readonly baseUrl: string,\n private readonly tokenCredential: TokenCredential,\n ) {}\n\n /**\n * Get a collection of resource from Graph API and\n * return an `AsyncIterable` of that resource\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *requestCollection<T>(\n path: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<T> {\n // upgrade to advanced query mode transparently when \"search\" is used\n // to stay backwards compatible.\n const appliedQueryMode = query?.search ? 'advanced' : queryMode ?? 'basic';\n\n // not needed for \"search\"\n // as of https://docs.microsoft.com/en-us/graph/aad-advanced-queries?tabs=http\n // even though a few other places say the opposite\n // - https://docs.microsoft.com/en-us/graph/api/user-list?view=graph-rest-1.0&tabs=http#request-headers\n // - https://docs.microsoft.com/en-us/graph/api/resources/group?view=graph-rest-1.0#properties\n if (appliedQueryMode === 'advanced' && (query?.filter || query?.select)) {\n query.count = true;\n }\n const headers: Record<string, string> =\n appliedQueryMode === 'advanced'\n ? {\n // Eventual consistency is required for advanced querying capabilities\n // like \"$search\" or parts of \"$filter\".\n // If a new user/group is not found, it'll eventually be imported on a subsequent read\n ConsistencyLevel: 'eventual',\n }\n : {};\n\n let response = await this.requestApi(path, query, headers);\n\n for (;;) {\n if (response.status !== 200) {\n await this.handleError(path, response);\n }\n\n const result = await response.json();\n\n // Graph API return array of collections\n const elements: T[] = result.value;\n\n yield* elements;\n\n // Follow cursor to the next page if one is available\n if (!result['@odata.nextLink']) {\n return;\n }\n\n response = await this.requestRaw(result['@odata.nextLink'], headers);\n }\n }\n\n /**\n * Abstract on top of {@link MicrosoftGraphClient.requestRaw}\n *\n * @public\n * @param path - Resource in Microsoft Graph\n * @param query - OData Query {@link ODataQuery}\n * @param headers - optional HTTP headers\n */\n async requestApi(\n path: string,\n query?: ODataQuery,\n headers?: Record<string, string>,\n ): Promise<Response> {\n const queryString = qs.stringify(\n {\n $search: query?.search,\n $filter: query?.filter,\n $select: query?.select?.join(','),\n $expand: query?.expand,\n $count: query?.count,\n $top: query?.top,\n },\n {\n addQueryPrefix: true,\n // Microsoft Graph doesn't like an encoded query string\n encode: false,\n },\n );\n\n return await this.requestRaw(\n `${this.baseUrl}/${path}${queryString}`,\n headers,\n );\n }\n\n /**\n * Makes a HTTP call to Graph API with token\n *\n * @param url - HTTP Endpoint of Graph API\n * @param headers - optional HTTP headers\n */\n async requestRaw(\n url: string,\n headers?: Record<string, string>,\n retryCount = 2,\n ): Promise<Response> {\n // Make sure that we always have a valid access token (might be cached)\n const urlObj = new URL(url);\n const token = await this.tokenCredential.getToken(\n `${urlObj.protocol}//${urlObj.hostname}/.default`,\n );\n\n if (!token) {\n throw new Error('Failed to obtain token from Azure Identity');\n }\n\n try {\n return await fetch(url, {\n headers: {\n ...headers,\n Authorization: `Bearer ${token.token}`,\n },\n });\n } catch (e: any) {\n if (e?.code === 'ETIMEDOUT' && retryCount > 0) {\n return this.requestRaw(url, headers, retryCount - 1);\n }\n throw e;\n }\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `User` from Graph API with size limit\n *\n * @param userId - The unique identifier for the `User` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getUserPhotoWithSizeLimit(\n userId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('users', userId, maxSize);\n }\n\n async getUserPhoto(\n userId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('users', userId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getUsers(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(\n `users`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * of `Group` from Graph API with size limit\n *\n * @param groupId - The unique identifier for the `Group` resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n async getGroupPhotoWithSizeLimit(\n groupId: string,\n maxSize: number,\n ): Promise<string | undefined> {\n return await this.getPhotoWithSizeLimit('groups', groupId, maxSize);\n }\n\n async getGroupPhoto(\n groupId: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n return await this.getPhoto('groups', groupId, sizeId);\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/group | Group}\n * from Graph API and return as `AsyncIterable`\n *\n * @public\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getGroups(\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.Group> {\n yield* this.requestCollection<MicrosoftGraph.Group>(\n `groups`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n *\n */\n async *getGroupMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<GroupMember> {\n yield* this.requestCollection<GroupMember>(\n `groups/${groupId}/members`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get a collection of\n * {@link https://docs.microsoft.com/en-us/graph/api/resources/user | User}\n * belonging to a `Group` from Graph API and return as `AsyncIterable`\n * @public\n * @param groupId - The unique identifier for the `Group` resource\n * @param query - OData Query {@link ODataQuery}\n * @param queryMode - Mode to use while querying. Some features are only available at \"advanced\".\n */\n async *getGroupUserMembers(\n groupId: string,\n query?: ODataQuery,\n queryMode?: 'basic' | 'advanced',\n ): AsyncIterable<MicrosoftGraph.User> {\n yield* this.requestCollection<MicrosoftGraph.User>(\n `groups/${groupId}/members/microsoft.graph.user/`,\n query,\n queryMode,\n );\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/organization | Organization}\n * from Graph API\n * @public\n * @param tenantId - The unique identifier for the `Organization` resource\n *\n */\n async getOrganization(\n tenantId: string,\n ): Promise<MicrosoftGraph.Organization> {\n const response = await this.requestApi(`organization/${tenantId}`);\n\n if (response.status !== 200) {\n await this.handleError(`organization/${tenantId}`, response);\n }\n\n return await response.json();\n }\n\n /**\n * Get {@link https://docs.microsoft.com/en-us/graph/api/resources/profilephoto | profilePhoto}\n * from Graph API\n *\n * @param entityName - type of parent resource, either `User` or `Group`\n * @param id - The unique identifier for the {@link entityName | entityName} resource\n * @param maxSize - Maximum pixel height of the photo\n *\n */\n private async getPhotoWithSizeLimit(\n entityName: string,\n id: string,\n maxSize: number,\n ): Promise<string | undefined> {\n const response = await this.requestApi(`${entityName}/${id}/photos`);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError(`${entityName} photos`, response);\n }\n\n const result = await response.json();\n const photos = result.value as MicrosoftGraph.ProfilePhoto[];\n let selectedPhoto: MicrosoftGraph.ProfilePhoto | undefined = undefined;\n\n // Find the biggest picture that is smaller than the max size\n for (const p of photos) {\n if (\n !selectedPhoto ||\n (p.height! >= selectedPhoto.height! && p.height! <= maxSize)\n ) {\n selectedPhoto = p;\n }\n }\n\n if (!selectedPhoto) {\n return undefined;\n }\n\n return await this.getPhoto(entityName, id, selectedPhoto.id!);\n }\n\n private async getPhoto(\n entityName: string,\n id: string,\n sizeId?: string,\n ): Promise<string | undefined> {\n const path = sizeId\n ? `${entityName}/${id}/photos/${sizeId}/$value`\n : `${entityName}/${id}/photo/$value`;\n const response = await this.requestApi(path);\n\n if (response.status === 404) {\n return undefined;\n } else if (response.status !== 200) {\n await this.handleError('photo', response);\n }\n\n return `data:image/jpeg;base64,${Buffer.from(\n await response.arrayBuffer(),\n ).toString('base64')}`;\n }\n\n private async handleError(path: string, response: Response): Promise<void> {\n const result = await response.json();\n const error = result.error as MicrosoftGraph.PublicError;\n\n throw new Error(\n `Error while reading ${path} from Microsoft Graph: ${error.code} - ${error.message}`,\n );\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n readTaskScheduleDefinitionFromConfig,\n TaskScheduleDefinition,\n} from '@backstage/backend-tasks';\nimport { Config } from '@backstage/config';\nimport { trimEnd } from 'lodash';\n\nconst DEFAULT_PROVIDER_ID = 'default';\nconst DEFAULT_TARGET = 'https://graph.microsoft.com/v1.0';\n\n/**\n * The configuration parameters for a single Microsoft Graph provider.\n *\n * @public\n */\nexport type MicrosoftGraphProviderConfig = {\n /**\n * Identifier of the provider which will be used i.e. at the location key for ingested entities.\n */\n id: string;\n\n /**\n * The prefix of the target that this matches on, e.g.\n * \"https://graph.microsoft.com/v1.0\", with no trailing slash.\n */\n target: string;\n /**\n * The auth authority used.\n *\n * E.g. \"https://login.microsoftonline.com\"\n */\n authority?: string;\n /**\n * The tenant whose org data we are interested in.\n */\n tenantId: string;\n /**\n * The OAuth client ID to use for authenticating requests.\n * If specified, ClientSecret must also be specified\n */\n clientId?: string;\n /**\n * The OAuth client secret to use for authenticating requests.\n * If specified, ClientId must also be specified\n */\n clientSecret?: string;\n /**\n * The filter to apply to extract users.\n *\n * E.g. \"accountEnabled eq true and userType eq 'member'\"\n */\n userFilter?: string;\n /**\n * The fields to be fetched on query.\n *\n * E.g. [\"id\", \"displayName\", \"description\"]\n */\n userSelect?: string[];\n /**\n * The \"expand\" argument to apply to users.\n *\n * E.g. \"manager\".\n */\n userExpand?: string;\n /**\n * The filter to apply to extract users by groups memberships.\n *\n * E.g. \"displayName eq 'Backstage Users'\"\n */\n userGroupMemberFilter?: string;\n /**\n * The search criteria to apply to extract users by groups memberships.\n *\n * E.g. \"\\\"displayName:-team\\\"\" would only match groups which contain '-team'\n */\n userGroupMemberSearch?: string;\n /**\n * The \"expand\" argument to apply to groups.\n *\n * E.g. \"member\".\n */\n groupExpand?: string;\n /**\n * The filter to apply to extract groups.\n *\n * E.g. \"securityEnabled eq false and mailEnabled eq true\"\n */\n groupFilter?: string;\n /**\n * The search criteria to apply to extract groups.\n *\n * E.g. \"\\\"displayName:-team\\\"\" would only match groups which contain '-team'\n */\n groupSearch?: string;\n\n /**\n * The fields to be fetched on query.\n *\n * E.g. [\"id\", \"displayName\", \"description\"]\n */\n groupSelect?: string[];\n\n /**\n * By default, the Microsoft Graph API only provides the basic feature set\n * for querying. Certain features are limited to advanced query capabilities\n * (see https://docs.microsoft.com/en-us/graph/aad-advanced-queries)\n * and need to be enabled.\n *\n * Some features like `$expand` are not available for advanced queries, though.\n */\n queryMode?: 'basic' | 'advanced';\n\n /**\n * Set to false to not load user photos.\n * This can be useful for huge organizations.\n */\n loadUserPhotos?: boolean;\n\n /**\n * Schedule configuration for refresh tasks.\n */\n schedule?: TaskScheduleDefinition;\n};\n\n/**\n * Parses configuration.\n *\n * @param config - The root of the msgraph config hierarchy\n *\n * @public\n * @deprecated Replaced by not exported `readProviderConfigs` and kept for backwards compatibility only.\n */\nexport function readMicrosoftGraphConfig(\n config: Config,\n): MicrosoftGraphProviderConfig[] {\n const providers: MicrosoftGraphProviderConfig[] = [];\n const providerConfigs = config.getOptionalConfigArray('providers') ?? [];\n\n for (const providerConfig of providerConfigs) {\n const target = trimEnd(\n providerConfig.getOptionalString('target') ?? DEFAULT_TARGET,\n '/',\n );\n const authority = providerConfig.getOptionalString('authority');\n\n const tenantId = providerConfig.getString('tenantId');\n const clientId = providerConfig.getOptionalString('clientId');\n const clientSecret = providerConfig.getOptionalString('clientSecret');\n\n const userExpand = providerConfig.getOptionalString('userExpand');\n const userFilter = providerConfig.getOptionalString('userFilter');\n const userSelect = providerConfig.getOptionalStringArray('userSelect');\n const userGroupMemberFilter = providerConfig.getOptionalString(\n 'userGroupMemberFilter',\n );\n const userGroupMemberSearch = providerConfig.getOptionalString(\n 'userGroupMemberSearch',\n );\n const groupExpand = providerConfig.getOptionalString('groupExpand');\n const groupFilter = providerConfig.getOptionalString('groupFilter');\n const groupSearch = providerConfig.getOptionalString('groupSearch');\n\n if (userFilter && userGroupMemberFilter) {\n throw new Error(\n `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,\n );\n }\n if (userFilter && userGroupMemberSearch) {\n throw new Error(\n `userGroupMemberSearch cannot be specified when userFilter is defined.`,\n );\n }\n\n const groupSelect = providerConfig.getOptionalStringArray('groupSelect');\n const queryMode = providerConfig.getOptionalString('queryMode');\n if (\n queryMode !== undefined &&\n queryMode !== 'basic' &&\n queryMode !== 'advanced'\n ) {\n throw new Error(`queryMode must be one of: basic, advanced`);\n }\n\n if (clientId && !clientSecret) {\n throw new Error(\n `clientSecret must be provided when clientId is defined.`,\n );\n }\n\n if (clientSecret && !clientId) {\n throw new Error(\n `clientId must be provided when clientSecret is defined.`,\n );\n }\n\n providers.push({\n id: target,\n target,\n authority,\n tenantId,\n clientId,\n clientSecret,\n userExpand,\n userFilter,\n userSelect,\n userGroupMemberFilter,\n userGroupMemberSearch,\n groupExpand,\n groupFilter,\n groupSearch,\n groupSelect,\n queryMode,\n });\n }\n\n return providers;\n}\n\n/**\n * Parses all configured providers.\n *\n * @param config - The root of the msgraph config hierarchy\n *\n * @public\n */\nexport function readProviderConfigs(\n config: Config,\n): MicrosoftGraphProviderConfig[] {\n const providersConfig = config.getOptionalConfig(\n 'catalog.providers.microsoftGraphOrg',\n );\n if (!providersConfig) {\n return [];\n }\n\n if (providersConfig.has('clientId')) {\n // simple/single config variant\n return [readProviderConfig(DEFAULT_PROVIDER_ID, providersConfig)];\n }\n\n return providersConfig.keys().map(id => {\n const providerConfig = providersConfig.getConfig(id);\n\n return readProviderConfig(id, providerConfig);\n });\n}\n\n/**\n * Parses a single configured provider by id.\n *\n * @param id - the id of the provider to parse\n * @param config - The root of the msgraph config hierarchy\n *\n * @public\n */\nexport function readProviderConfig(\n id: string,\n config: Config,\n): MicrosoftGraphProviderConfig {\n const target = trimEnd(\n config.getOptionalString('target') ?? DEFAULT_TARGET,\n '/',\n );\n const authority = config.getOptionalString('authority');\n\n const tenantId = config.getString('tenantId');\n const clientId = config.getOptionalString('clientId');\n const clientSecret = config.getOptionalString('clientSecret');\n\n const userExpand = config.getOptionalString('user.expand');\n const userFilter = config.getOptionalString('user.filter');\n const userSelect = config.getOptionalStringArray('user.select');\n const loadUserPhotos = config.getOptionalBoolean('user.loadPhotos');\n\n const groupExpand = config.getOptionalString('group.expand');\n const groupFilter = config.getOptionalString('group.filter');\n const groupSearch = config.getOptionalString('group.search');\n const groupSelect = config.getOptionalStringArray('group.select');\n\n const queryMode = config.getOptionalString('queryMode');\n if (\n queryMode !== undefined &&\n queryMode !== 'basic' &&\n queryMode !== 'advanced'\n ) {\n throw new Error(`queryMode must be one of: basic, advanced`);\n }\n\n const userGroupMemberFilter = config.getOptionalString(\n 'userGroupMember.filter',\n );\n const userGroupMemberSearch = config.getOptionalString(\n 'userGroupMember.search',\n );\n\n if (userFilter && userGroupMemberFilter) {\n throw new Error(\n `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`,\n );\n }\n if (userFilter && userGroupMemberSearch) {\n throw new Error(\n `userGroupMemberSearch cannot be specified when userFilter is defined.`,\n );\n }\n\n if (clientId && !clientSecret) {\n throw new Error(`clientSecret must be provided when clientId is defined.`);\n }\n\n if (clientSecret && !clientId) {\n throw new Error(`clientId must be provided when clientSecret is defined.`);\n }\n\n const schedule = config.has('schedule')\n ? readTaskScheduleDefinitionFromConfig(config.getConfig('schedule'))\n : undefined;\n\n return {\n id,\n target,\n authority,\n clientId,\n clientSecret,\n tenantId,\n userExpand,\n userFilter,\n userSelect,\n loadUserPhotos,\n groupExpand,\n groupFilter,\n groupSearch,\n groupSelect,\n queryMode,\n userGroupMemberFilter,\n userGroupMemberSearch,\n schedule,\n };\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The (primary) user email. Also used by the Microsoft auth provider to resolve the User entity.\n *\n * @public\n */\nexport const MICROSOFT_EMAIL_ANNOTATION = 'microsoft.com/email';\n\n/**\n * The tenant id used by the Microsoft Graph API\n *\n * @public\n */\nexport const MICROSOFT_GRAPH_TENANT_ID_ANNOTATION =\n 'graph.microsoft.com/tenant-id';\n\n/**\n * The group id used by the Microsoft Graph API\n *\n * @public\n */\nexport const MICROSOFT_GRAPH_GROUP_ID_ANNOTATION =\n 'graph.microsoft.com/group-id';\n\n/**\n * The user id used by the Microsoft Graph API\n *\n * @public\n */\nexport const MICROSOFT_GRAPH_USER_ID_ANNOTATION = 'graph.microsoft.com/user-id';\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Takes an input string and cleans it up to become suitable as an entity name.\n *\n * @public\n */\nexport function normalizeEntityName(name: string): string {\n let cleaned = name\n .trim()\n .toLocaleLowerCase()\n .replace(/[^a-zA-Z0-9_\\-\\.]/g, '_');\n\n // invalid to end with _\n while (cleaned.endsWith('_')) {\n cleaned = cleaned.substring(0, cleaned.length - 1);\n }\n\n // cleans up format for groups like 'my group (Reader)'\n while (cleaned.includes('__')) {\n // replaceAll from node.js >= 15\n cleaned = cleaned.replace('__', '_');\n }\n\n return cleaned;\n}\n","/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n MICROSOFT_EMAIL_ANNOTATION,\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n} from './constants';\nimport { normalizeEntityName } from './helper';\nimport { GroupEntity, UserEntity } from '@backstage/catalog-model';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\n\n/**\n * The default implementation of the transformation from a graph organization\n * entry to a Group entity.\n *\n * @public\n */\nexport async function defaultOrganizationTransformer(\n organization: MicrosoftGraph.Organization,\n): Promise<GroupEntity | undefined> {\n if (!organization.id || !organization.displayName) {\n return undefined;\n }\n\n const name = normalizeEntityName(organization.displayName!);\n return {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Group',\n metadata: {\n name: name,\n description: organization.displayName!,\n annotations: {\n [MICROSOFT_GRAPH_TENANT_ID_ANNOTATION]: organization.id!,\n },\n },\n spec: {\n type: 'root',\n profile: {\n displayName: organization.displayName!,\n },\n children: [],\n },\n };\n}\n\nfunction extractGroupName(group: MicrosoftGraph.Group): string {\n if (group.securityEnabled) {\n return group.displayName as string;\n }\n return (group.mailNickname || group.displayName) as string;\n}\n\n/**\n * The default implementation of the transformation from a graph group entry to\n * a Group entity.\n *\n * @public\n */\nexport async function defaultGroupTransformer(\n group: MicrosoftGraph.Group,\n groupPhoto?: string,\n): Promise<GroupEntity | undefined> {\n if (!group.id || !group.displayName) {\n return undefined;\n }\n\n const name = normalizeEntityName(extractGroupName(group));\n const entity: GroupEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'Group',\n metadata: {\n name: name,\n annotations: {\n [MICROSOFT_GRAPH_GROUP_ID_ANNOTATION]: group.id,\n },\n },\n spec: {\n type: 'team',\n profile: {},\n children: [],\n },\n };\n\n if (group.description) {\n entity.metadata.description = group.description;\n }\n if (group.displayName) {\n entity.spec.profile!.displayName = group.displayName;\n }\n if (group.mail) {\n entity.spec.profile!.email = group.mail;\n }\n if (groupPhoto) {\n entity.spec.profile!.picture = groupPhoto;\n }\n\n return entity;\n}\n\n/**\n * The default implementation of the transformation from a graph user entry to\n * a User entity.\n *\n * @public\n */\nexport async function defaultUserTransformer(\n user: MicrosoftGraph.User,\n userPhoto?: string,\n): Promise<UserEntity | undefined> {\n if (!user.id || !user.displayName || !user.mail) {\n return undefined;\n }\n\n const name = normalizeEntityName(user.mail);\n const entity: UserEntity = {\n apiVersion: 'backstage.io/v1alpha1',\n kind: 'User',\n metadata: {\n name,\n annotations: {\n [MICROSOFT_EMAIL_ANNOTATION]: user.mail!,\n [MICROSOFT_GRAPH_USER_ID_ANNOTATION]: user.id!,\n },\n },\n spec: {\n profile: {\n displayName: user.displayName!,\n email: user.mail!,\n\n // TODO: Additional fields?\n // jobTitle: user.jobTitle || undefined,\n // officeLocation: user.officeLocation || undefined,\n // mobilePhone: user.mobilePhone || undefined,\n },\n memberOf: [],\n },\n };\n\n if (userPhoto) {\n entity.spec.profile!.picture = userPhoto;\n }\n\n return entity;\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { GroupEntity, UserEntity } from '@backstage/catalog-model';\n\n// TODO: Copied from plugin-catalog-backend, but we could also export them from\n// there. Or move them to catalog-model.\n\nexport function buildOrgHierarchy(groups: GroupEntity[]) {\n const groupsByName = new Map(groups.map(g => [g.metadata.name, g]));\n\n //\n // Make sure that g.parent.children contain g\n //\n\n for (const group of groups) {\n const selfName = group.metadata.name;\n const parentName = group.spec.parent;\n if (parentName) {\n const parent = groupsByName.get(parentName);\n if (parent && !parent.spec.children.includes(selfName)) {\n parent.spec.children.push(selfName);\n }\n }\n }\n\n //\n // Make sure that g.children.parent is g\n //\n\n for (const group of groups) {\n const selfName = group.metadata.name;\n for (const childName of group.spec.children) {\n const child = groupsByName.get(childName);\n if (child && !child.spec.parent) {\n child.spec.parent = selfName;\n }\n }\n }\n}\n\n// Ensure that users have their transitive group memberships. Requires that\n// the groups were previously processed with buildOrgHierarchy()\nexport function buildMemberOf(groups: GroupEntity[], users: UserEntity[]) {\n const groupsByName = new Map(groups.map(g => [g.metadata.name, g]));\n\n users.forEach(user => {\n const transitiveMemberOf = new Set<string>();\n\n const todo = [\n ...(user.spec.memberOf ?? []),\n ...groups\n .filter(g => g.spec.members?.includes(user.metadata.name))\n .map(g => g.metadata.name),\n ];\n\n for (;;) {\n const current = todo.pop();\n if (!current) {\n break;\n }\n\n if (!transitiveMemberOf.has(current)) {\n transitiveMemberOf.add(current);\n const group = groupsByName.get(current);\n if (group?.spec.parent) {\n todo.push(group.spec.parent);\n }\n }\n }\n\n user.spec.memberOf = [...transitiveMemberOf];\n });\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n GroupEntity,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport limiterFactory from 'p-limit';\nimport { MicrosoftGraphClient } from './client';\nimport {\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n} from './constants';\nimport { buildMemberOf, buildOrgHierarchy } from './org';\nimport {\n GroupTransformer,\n OrganizationTransformer,\n UserTransformer,\n} from './types';\nimport {\n defaultGroupTransformer,\n defaultOrganizationTransformer,\n defaultUserTransformer,\n} from './defaultTransformers';\nimport * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\nconst PAGE_SIZE = 999;\n\nexport async function readMicrosoftGraphUsers(\n client: MicrosoftGraphClient,\n options: {\n queryMode?: 'basic' | 'advanced';\n userExpand?: string;\n userFilter?: string;\n userSelect?: string[];\n loadUserPhotos?: boolean;\n transformer?: UserTransformer;\n logger: LoggerService;\n },\n): Promise<{\n users: UserEntity[]; // With all relations empty\n}> {\n const users = client.getUsers(\n {\n filter: options.userFilter,\n expand: options.userExpand,\n select: options.userSelect,\n top: PAGE_SIZE,\n },\n options.queryMode,\n );\n\n return {\n users: await transformUsers(\n client,\n users,\n options.logger,\n options.loadUserPhotos,\n options.transformer,\n ),\n };\n}\n\nexport async function readMicrosoftGraphUsersInGroups(\n client: MicrosoftGraphClient,\n options: {\n queryMode?: 'basic' | 'advanced';\n userExpand?: string;\n userFilter?: string;\n userSelect?: string[];\n loadUserPhotos?: boolean;\n userGroupMemberSearch?: string;\n userGroupMemberFilter?: string;\n groupExpand?: string;\n transformer?: UserTransformer;\n logger: LoggerService;\n },\n): Promise<{\n users: UserEntity[]; // With all relations empty\n}> {\n const limiter = limiterFactory(10);\n\n const userGroupMemberPromises: Promise<void>[] = [];\n const userGroupMembers = new Map<string, MicrosoftGraph.User>();\n\n for await (const group of client.getGroups(\n {\n expand: options.groupExpand,\n filter: options.userGroupMemberFilter,\n search: options.userGroupMemberSearch,\n select: ['id', 'displayName'],\n top: PAGE_SIZE,\n },\n options.queryMode,\n )) {\n // Process all groups in parallel, otherwise it can take quite some time\n userGroupMemberPromises.push(\n limiter(async () => {\n let groupMemberCount = 0;\n for await (const user of client.getGroupUserMembers(\n group.id!,\n {\n expand: options.userExpand,\n filter: options.userFilter,\n select: options.userSelect,\n top: PAGE_SIZE,\n },\n options.queryMode,\n )) {\n userGroupMembers.set(user.id!, user);\n groupMemberCount++;\n }\n options.logger.debug('Read users from group', {\n groupId: group.id,\n groupName: group.displayName,\n memberCount: groupMemberCount,\n });\n }),\n );\n }\n\n // Wait for all group members\n await Promise.all(userGroupMemberPromises);\n\n options.logger.info('Read users from group membership', {\n groupCount: userGroupMemberPromises.length,\n userCount: userGroupMembers.size,\n });\n\n return {\n users: await transformUsers(\n client,\n userGroupMembers.values(),\n options.logger,\n options.loadUserPhotos,\n options.transformer,\n ),\n };\n}\n\nexport async function readMicrosoftGraphOrganization(\n client: MicrosoftGraphClient,\n tenantId: string,\n options?: { transformer?: OrganizationTransformer },\n): Promise<{\n rootGroup?: GroupEntity; // With all relations empty\n}> {\n // For now we expect a single root organization\n const organization = await client.getOrganization(tenantId);\n const transformer = options?.transformer ?? defaultOrganizationTransformer;\n const rootGroup = await transformer(organization);\n\n return { rootGroup };\n}\n\nexport async function readMicrosoftGraphGroups(\n client: MicrosoftGraphClient,\n tenantId: string,\n options?: {\n queryMode?: 'basic' | 'advanced';\n groupExpand?: string;\n groupFilter?: string;\n groupSearch?: string;\n groupSelect?: string[];\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n },\n): Promise<{\n groups: GroupEntity[]; // With all relations empty\n rootGroup: GroupEntity | undefined; // With all relations empty\n groupMember: Map<string, Set<string>>;\n groupMemberOf: Map<string, Set<string>>;\n}> {\n const groups: GroupEntity[] = [];\n const groupMember: Map<string, Set<string>> = new Map();\n const groupMemberOf: Map<string, Set<string>> = new Map();\n const limiter = limiterFactory(10);\n\n const { rootGroup } = await readMicrosoftGraphOrganization(client, tenantId, {\n transformer: options?.organizationTransformer,\n });\n if (rootGroup) {\n groupMember.set(rootGroup.metadata.name, new Set<string>());\n groups.push(rootGroup);\n }\n\n const transformer = options?.groupTransformer ?? defaultGroupTransformer;\n const promises: Promise<void>[] = [];\n\n for await (const group of client.getGroups(\n {\n expand: options?.groupExpand,\n filter: options?.groupFilter,\n search: options?.groupSearch,\n select: options?.groupSelect,\n top: PAGE_SIZE,\n },\n options?.queryMode,\n )) {\n // Process all groups in parallel, otherwise it can take quite some time\n promises.push(\n limiter(async () => {\n // TODO: Loading groups photos doesn't work right now as Microsoft Graph\n // doesn't allows this yet: https://microsoftgraph.uservoice.com/forums/920506-microsoft-graph-feature-requests/suggestions/37884922-allow-application-to-set-or-update-a-group-s-photo\n /* const groupPhoto = await client.getGroupPhotoWithSizeLimit(\n group.id!,\n // We are limiting the photo size, as groups with full resolution photos\n // can make the Backstage API slow\n 120,\n );*/\n\n const entity = await transformer(group /* , groupPhoto*/);\n\n if (!entity) {\n return;\n }\n\n for await (const member of client.getGroupMembers(group.id!, {\n top: PAGE_SIZE,\n })) {\n if (!member.id) {\n continue;\n }\n\n if (member['@odata.type'] === '#microsoft.graph.user') {\n ensureItem(groupMemberOf, member.id, group.id!);\n }\n\n if (member['@odata.type'] === '#microsoft.graph.group') {\n ensureItem(groupMember, group.id!, member.id);\n }\n }\n\n groups.push(entity);\n }),\n );\n }\n\n // Wait for all group members and photos to be loaded\n await Promise.all(promises);\n\n return {\n groups,\n rootGroup,\n groupMember,\n groupMemberOf,\n };\n}\n\nexport function resolveRelations(\n rootGroup: GroupEntity | undefined,\n groups: GroupEntity[],\n users: UserEntity[],\n groupMember: Map<string, Set<string>>,\n groupMemberOf: Map<string, Set<string>>,\n) {\n // Build reference lookup tables, we reference them by the id the the graph\n const groupMap: Map<string, GroupEntity> = new Map(); // by group-id or tenant-id\n\n for (const group of groups) {\n if (group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION]) {\n groupMap.set(\n group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION],\n group,\n );\n }\n if (group.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION]) {\n groupMap.set(\n group.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION],\n group,\n );\n }\n }\n\n // Resolve all member relationships into the reverse direction\n const parentGroups = new Map<string, Set<string>>();\n\n groupMember.forEach((members, groupId) =>\n members.forEach(m => ensureItem(parentGroups, m, groupId)),\n );\n\n // Make sure every group (except root) has at least one parent. If the parent is missing, add the root.\n if (rootGroup) {\n const tenantId =\n rootGroup.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];\n\n groups.forEach(group => {\n const groupId =\n group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION];\n\n if (!groupId) {\n return;\n }\n\n if (retrieveItems(parentGroups, groupId).size === 0) {\n ensureItem(parentGroups, groupId, tenantId);\n ensureItem(groupMember, tenantId, groupId);\n }\n });\n }\n\n groups.forEach(group => {\n const id =\n group.metadata.annotations![MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ??\n group.metadata.annotations![MICROSOFT_GRAPH_TENANT_ID_ANNOTATION];\n\n retrieveItems(groupMember, id).forEach(m => {\n const childGroup = groupMap.get(m);\n if (childGroup) {\n group.spec.children.push(stringifyEntityRef(childGroup));\n }\n });\n\n retrieveItems(parentGroups, id).forEach(p => {\n const parentGroup = groupMap.get(p);\n if (parentGroup) {\n // TODO: Only having a single parent group might not match every companies model, but fine for now.\n group.spec.parent = stringifyEntityRef(parentGroup);\n }\n });\n });\n\n // Make sure that all groups have proper parents and children\n buildOrgHierarchy(groups);\n\n // Set relations for all users\n users.forEach(user => {\n const id = user.metadata.annotations![MICROSOFT_GRAPH_USER_ID_ANNOTATION];\n\n retrieveItems(groupMemberOf, id).forEach(p => {\n const parentGroup = groupMap.get(p);\n if (parentGroup) {\n if (!user.spec.memberOf) {\n user.spec.memberOf = [];\n }\n user.spec.memberOf.push(stringifyEntityRef(parentGroup));\n }\n });\n });\n\n // Make sure all transitive memberships are available\n buildMemberOf(groups, users);\n}\n\n/**\n * Reads an entire org as Group and User entities.\n *\n * @public\n */\nexport async function readMicrosoftGraphOrg(\n client: MicrosoftGraphClient,\n tenantId: string,\n options: {\n userExpand?: string;\n userFilter?: string;\n userSelect?: string[];\n loadUserPhotos?: boolean;\n userGroupMemberSearch?: string;\n userGroupMemberFilter?: string;\n groupExpand?: string;\n groupSearch?: string;\n groupFilter?: string;\n groupSelect?: string[];\n queryMode?: 'basic' | 'advanced';\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n logger: LoggerService;\n },\n): Promise<{ users: UserEntity[]; groups: GroupEntity[] }> {\n let users: UserEntity[] = [];\n\n if (options.userGroupMemberFilter || options.userGroupMemberSearch) {\n const { users: usersInGroups } = await readMicrosoftGraphUsersInGroups(\n client,\n {\n queryMode: options.queryMode,\n userExpand: options.userExpand,\n userFilter: options.userFilter,\n userSelect: options.userSelect,\n userGroupMemberFilter: options.userGroupMemberFilter,\n userGroupMemberSearch: options.userGroupMemberSearch,\n loadUserPhotos: options.loadUserPhotos,\n transformer: options.userTransformer,\n logger: options.logger,\n },\n );\n users = usersInGroups;\n } else {\n const { users: usersWithFilter } = await readMicrosoftGraphUsers(client, {\n queryMode: options.queryMode,\n userExpand: options.userExpand,\n userFilter: options.userFilter,\n userSelect: options.userSelect,\n loadUserPhotos: options.loadUserPhotos,\n transformer: options.userTransformer,\n logger: options.logger,\n });\n users = usersWithFilter;\n }\n const { groups, rootGroup, groupMember, groupMemberOf } =\n await readMicrosoftGraphGroups(client, tenantId, {\n queryMode: options.queryMode,\n groupExpand: options.groupExpand,\n groupFilter: options.groupFilter,\n groupSearch: options.groupSearch,\n groupSelect: options.groupSelect,\n groupTransformer: options.groupTransformer,\n organizationTransformer: options.organizationTransformer,\n });\n\n resolveRelations(rootGroup, groups, users, groupMember, groupMemberOf);\n users.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));\n groups.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name));\n\n return { users, groups };\n}\n\nasync function transformUsers(\n client: MicrosoftGraphClient,\n users: Iterable<MicrosoftGraph.User> | AsyncIterable<MicrosoftGraph.User>,\n logger: LoggerService,\n loadUserPhotos = true,\n transformer?: UserTransformer,\n) {\n const limiter = limiterFactory(10);\n\n const resolvedTransformer = transformer ?? defaultUserTransformer;\n const promises: Promise<void>[] = [];\n const entities: UserEntity[] = [];\n\n // Process all users in parallel, otherwise it can take quite some time\n for await (const user of users) {\n promises.push(\n limiter(async () => {\n let userPhoto;\n try {\n if (loadUserPhotos) {\n userPhoto = await client.getUserPhotoWithSizeLimit(\n user.id!,\n // We are limiting the photo size, as users with full resolution photos\n // can make the Backstage API slow\n 120,\n );\n }\n } catch (e) {\n logger.warn(`Unable to load user photo for`, {\n user: user.id,\n error: e,\n });\n }\n\n const entity = await resolvedTransformer(user, userPhoto);\n\n if (entity) {\n entities.push(entity);\n }\n }),\n );\n }\n\n // Wait for all users and photos to be downloaded\n await Promise.all(promises);\n\n logger.debug('Finished transforming users', {\n microsoftUserCount: promises.length,\n backstageUserCount: entities.length,\n });\n return entities;\n}\n\nfunction ensureItem(\n target: Map<string, Set<string>>,\n key: string,\n value: string,\n) {\n let set = target.get(key);\n if (!set) {\n set = new Set();\n target.set(key, set);\n }\n set!.add(value);\n}\n\nfunction retrieveItems(\n target: Map<string, Set<string>>,\n key: string,\n): Set<string> {\n return target.get(key) ?? new Set();\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';\nimport {\n ANNOTATION_LOCATION,\n ANNOTATION_ORIGIN_LOCATION,\n Entity,\n} from '@backstage/catalog-model';\nimport { Config } from '@backstage/config';\nimport {\n EntityProvider,\n EntityProviderConnection,\n} from '@backstage/plugin-catalog-node';\nimport { merge } from 'lodash';\nimport * as uuid from 'uuid';\nimport {\n GroupTransformer,\n MICROSOFT_GRAPH_GROUP_ID_ANNOTATION,\n MICROSOFT_GRAPH_TENANT_ID_ANNOTATION,\n MICROSOFT_GRAPH_USER_ID_ANNOTATION,\n MicrosoftGraphClient,\n MicrosoftGraphProviderConfig,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { readProviderConfigs } from '../microsoftGraph/config';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n/**\n * Options for {@link MicrosoftGraphOrgEntityProvider}.\n *\n * @public\n */\nexport type MicrosoftGraphOrgEntityProviderOptions =\n | MicrosoftGraphOrgEntityProviderLegacyOptions\n | {\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule?: 'manual' | TaskRunner;\n\n /**\n * Scheduler used to schedule refreshes based on\n * the schedule config.\n */\n scheduler?: PluginTaskScheduler;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n userTransformer?: UserTransformer | Record<string, UserTransformer>;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n groupTransformer?: GroupTransformer | Record<string, GroupTransformer>;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n * Optionally, you can pass separate transformers per provider ID.\n */\n organizationTransformer?:\n | OrganizationTransformer\n | Record<string, OrganizationTransformer>;\n };\n\n/**\n * Legacy options for {@link MicrosoftGraphOrgEntityProvider}\n * based on `catalog.processors.microsoftGraphOrg`.\n *\n * @public\n * @deprecated This interface exists for backwards compatibility only and will be removed in the future.\n */\nexport interface MicrosoftGraphOrgEntityProviderLegacyOptions {\n /**\n * A unique, stable identifier for this provider.\n *\n * @example \"production\"\n */\n id: string;\n\n /**\n * The target that this provider should consume.\n *\n * Should exactly match the \"target\" field of one of the provider\n * configuration entries.\n */\n target: string;\n\n /**\n * The logger to use.\n */\n logger: LoggerService;\n\n /**\n * The refresh schedule to use.\n *\n * @remarks\n *\n * If you pass in 'manual', you are responsible for calling the `read` method\n * manually at some interval.\n *\n * But more commonly you will pass in the result of\n * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule: 'manual' | TaskRunner;\n\n /**\n * The function that transforms a user entry in msgraph to an entity.\n */\n userTransformer?: UserTransformer;\n\n /**\n * The function that transforms a group entry in msgraph to an entity.\n */\n groupTransformer?: GroupTransformer;\n\n /**\n * The function that transforms an organization entry in msgraph to an entity.\n */\n organizationTransformer?: OrganizationTransformer;\n}\n\n/**\n * Reads user and group entries out of Microsoft Graph, and provides them as\n * User and Group entities for the catalog.\n *\n * @public\n */\nexport class MicrosoftGraphOrgEntityProvider implements EntityProvider {\n private connection?: EntityProviderConnection;\n private scheduleFn?: () => Promise<void>;\n\n static fromConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderOptions,\n ): MicrosoftGraphOrgEntityProvider[] {\n if ('id' in options) {\n return [\n MicrosoftGraphOrgEntityProvider.fromLegacyConfig(configRoot, options),\n ];\n }\n\n if (!options.schedule && !options.scheduler) {\n throw new Error('Either schedule or scheduler must be provided.');\n }\n\n function getTransformer<T extends Function>(\n id: string,\n transformers?: T | Record<string, T>,\n ): T | undefined {\n if (['undefined', 'function'].includes(typeof transformers)) {\n return transformers as T;\n }\n\n return (transformers as Record<string, T>)[id];\n }\n\n return readProviderConfigs(configRoot).map(providerConfig => {\n if (!options.schedule && !providerConfig.schedule) {\n throw new Error(\n `No schedule provided neither via code nor config for MicrosoftGraphOrgEntityProvider:${providerConfig.id}.`,\n );\n }\n\n const taskRunner =\n options.schedule ??\n options.scheduler!.createScheduledTaskRunner(providerConfig.schedule!);\n\n const provider = new MicrosoftGraphOrgEntityProvider({\n id: providerConfig.id,\n provider: providerConfig,\n logger: options.logger,\n userTransformer: getTransformer(\n providerConfig.id,\n options.userTransformer,\n ),\n groupTransformer: getTransformer(\n providerConfig.id,\n options.groupTransformer,\n ),\n organizationTransformer: getTransformer(\n providerConfig.id,\n options.organizationTransformer,\n ),\n });\n\n if (taskRunner !== 'manual') {\n provider.schedule(taskRunner);\n }\n\n return provider;\n });\n }\n\n /**\n * @deprecated Exists for backwards compatibility only and will be removed in the future.\n */\n private static fromLegacyConfig(\n configRoot: Config,\n options: MicrosoftGraphOrgEntityProviderLegacyOptions,\n ): MicrosoftGraphOrgEntityProvider {\n options.logger.warn(\n 'Deprecated msgraph config \"catalog.processors.microsoftGraphOrg\" used. Use \"catalog.providers.microsoftGraphOrg\" instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1',\n );\n const config = configRoot.getOptionalConfig(\n 'catalog.processors.microsoftGraphOrg',\n );\n const providers = config ? readMicrosoftGraphConfig(config) : [];\n const provider = providers.find(p => options.target.startsWith(p.target));\n\n if (!provider) {\n throw new Error(\n `There is no Microsoft Graph Org provider that matches \"${options.target}\". Please add a configuration entry for it under \"catalog.processors.microsoftGraphOrg.providers\".`,\n );\n }\n\n const logger = options.logger.child({\n target: options.target,\n });\n\n const result = new MicrosoftGraphOrgEntityProvider({\n id: options.id,\n userTransformer: options.userTransformer,\n groupTransformer: options.groupTransformer,\n organizationTransformer: options.organizationTransformer,\n logger,\n provider,\n });\n\n if (options.schedule !== 'manual') {\n result.schedule(options.schedule);\n }\n\n return result;\n }\n\n constructor(\n private options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n },\n ) {}\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.getProviderName} */\n getProviderName() {\n return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-backend#EntityProvider.connect} */\n async connect(connection: EntityProviderConnection) {\n this.connection = connection;\n await this.scheduleFn?.();\n }\n\n /**\n * Runs one complete ingestion loop. Call this method regularly at some\n * appropriate cadence.\n */\n async read(options?: { logger?: LoggerService }) {\n if (!this.connection) {\n throw new Error('Not initialized');\n }\n\n const logger = options?.logger ?? this.options.logger;\n const provider = this.options.provider;\n const { markReadComplete } = trackProgress(logger);\n const client = MicrosoftGraphClient.create(this.options.provider);\n const { users, groups } = await readMicrosoftGraphOrg(\n client,\n provider.tenantId,\n {\n userExpand: provider.userExpand,\n userFilter: provider.userFilter,\n userSelect: provider.userSelect,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n queryMode: provider.queryMode,\n groupTransformer: this.options.groupTransformer,\n userTransformer: this.options.userTransformer,\n organizationTransformer: this.options.organizationTransformer,\n logger: logger,\n },\n );\n\n const { markCommitComplete } = markReadComplete({ users, groups });\n\n await this.connection.applyMutation({\n type: 'full',\n entities: [...users, ...groups].map(entity => ({\n locationKey: `msgraph-org-provider:${this.options.id}`,\n entity: withLocations(this.options.id, entity),\n })),\n });\n\n markCommitComplete();\n }\n\n private schedule(taskRunner: TaskRunner) {\n this.scheduleFn = async () => {\n const id = `${this.getProviderName()}:refresh`;\n await taskRunner.run({\n id,\n fn: async () => {\n const logger = this.options.logger.child({\n class: MicrosoftGraphOrgEntityProvider.prototype.constructor.name,\n taskId: id,\n taskInstanceId: uuid.v4(),\n });\n\n try {\n await this.read({ logger });\n } catch (error) {\n logger.error(\n `${this.getProviderName()} refresh failed, ${error}`,\n error,\n );\n }\n },\n });\n };\n }\n}\n\n// Helps wrap the timing and logging behaviors\nfunction trackProgress(logger: LoggerService) {\n let timestamp = Date.now();\n let summary: string;\n\n logger.info('Reading msgraph users and groups');\n\n function markReadComplete(read: { users: unknown[]; groups: unknown[] }) {\n summary = `${read.users.length} msgraph users and ${read.groups.length} msgraph groups`;\n const readDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n timestamp = Date.now();\n logger.info(`Read ${summary} in ${readDuration} seconds. Committing...`);\n return { markCommitComplete };\n }\n\n function markCommitComplete() {\n const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n logger.info(`Committed ${summary} in ${commitDuration} seconds.`);\n }\n\n return { markReadComplete };\n}\n\n// Makes sure that emitted entities have a proper location based on their uuid\nexport function withLocations(providerId: string, entity: Entity): Entity {\n const uid =\n entity.metadata.annotations?.[MICROSOFT_GRAPH_USER_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_GROUP_ID_ANNOTATION] ||\n entity.metadata.annotations?.[MICROSOFT_GRAPH_TENANT_ID_ANNOTATION] ||\n entity.metadata.name;\n const location = `msgraph:${providerId}/${encodeURIComponent(uid)}`;\n return merge(\n {\n metadata: {\n annotations: {\n [ANNOTATION_LOCATION]: location,\n [ANNOTATION_ORIGIN_LOCATION]: location,\n },\n },\n },\n entity,\n ) as Entity;\n}\n"],"names":["ClientSecretCredential","DefaultAzureCredential","qs","fetch","trimEnd","readTaskScheduleDefinitionFromConfig","limiterFactory","stringifyEntityRef","uuid","merge","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION"],"mappings":"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"}
package/dist/index.cjs.js CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var MicrosoftGraphOrgEntityProvider = require('./cjs/MicrosoftGraphOrgEntityProvider-DZcLVfiM.cjs.js');
3
+ var MicrosoftGraphOrgEntityProvider = require('./cjs/MicrosoftGraphOrgEntityProvider-Cyc0qWct.cjs.js');
4
4
  var pluginCatalogNode = require('@backstage/plugin-catalog-node');
5
5
  require('@backstage/catalog-model');
6
6
  require('lodash');
@@ -11,19 +11,20 @@ require('qs');
11
11
  require('@backstage/backend-tasks');
12
12
  require('p-limit');
13
13
 
14
- var __defProp = Object.defineProperty;
15
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
16
- var __publicField = (obj, key, value) => {
17
- __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
18
- return value;
19
- };
20
14
  class MicrosoftGraphOrgReaderProcessor {
15
+ providers;
16
+ logger;
17
+ userTransformer;
18
+ groupTransformer;
19
+ organizationTransformer;
20
+ static fromConfig(config, options) {
21
+ const c = config.getOptionalConfig("catalog.processors.microsoftGraphOrg");
22
+ return new MicrosoftGraphOrgReaderProcessor({
23
+ ...options,
24
+ providers: c ? MicrosoftGraphOrgEntityProvider.readMicrosoftGraphConfig(c) : []
25
+ });
26
+ }
21
27
  constructor(options) {
22
- __publicField(this, "providers");
23
- __publicField(this, "logger");
24
- __publicField(this, "userTransformer");
25
- __publicField(this, "groupTransformer");
26
- __publicField(this, "organizationTransformer");
27
28
  options.logger.warn(
28
29
  "MicrosoftGraphOrgReaderProcessor is deprecated. Please use MicrosoftGraphOrgEntityProvider instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1"
29
30
  );
@@ -33,13 +34,6 @@ class MicrosoftGraphOrgReaderProcessor {
33
34
  this.groupTransformer = options.groupTransformer;
34
35
  this.organizationTransformer = options.organizationTransformer;
35
36
  }
36
- static fromConfig(config, options) {
37
- const c = config.getOptionalConfig("catalog.processors.microsoftGraphOrg");
38
- return new MicrosoftGraphOrgReaderProcessor({
39
- ...options,
40
- providers: c ? MicrosoftGraphOrgEntityProvider.readMicrosoftGraphConfig(c) : []
41
- });
42
- }
43
37
  getProcessorName() {
44
38
  return "MicrosoftGraphOrgReaderProcessor";
45
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/processors/MicrosoftGraphOrgReaderProcessor.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport {\n CatalogProcessor,\n CatalogProcessorEmit,\n processingResult,\n} from '@backstage/plugin-catalog-node';\nimport { LocationSpec } from '@backstage/plugin-catalog-common';\nimport {\n GroupTransformer,\n MicrosoftGraphClient,\n MicrosoftGraphProviderConfig,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n/**\n * Extracts teams and users out of the Microsoft Graph API.\n *\n * @public\n * @deprecated Use the MicrosoftGraphOrgEntityProvider instead.\n */\nexport class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor {\n private readonly providers: MicrosoftGraphProviderConfig[];\n private readonly logger: LoggerService;\n private readonly userTransformer?: UserTransformer;\n private readonly groupTransformer?: GroupTransformer;\n private readonly organizationTransformer?: OrganizationTransformer;\n\n static fromConfig(\n config: Config,\n options: {\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n },\n ) {\n const c = config.getOptionalConfig('catalog.processors.microsoftGraphOrg');\n return new MicrosoftGraphOrgReaderProcessor({\n ...options,\n providers: c ? readMicrosoftGraphConfig(c) : [],\n });\n }\n\n constructor(options: {\n providers: MicrosoftGraphProviderConfig[];\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n }) {\n options.logger.warn(\n 'MicrosoftGraphOrgReaderProcessor is deprecated. Please use MicrosoftGraphOrgEntityProvider instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1',\n );\n this.providers = options.providers;\n this.logger = options.logger;\n this.userTransformer = options.userTransformer;\n this.groupTransformer = options.groupTransformer;\n this.organizationTransformer = options.organizationTransformer;\n }\n\n getProcessorName(): string {\n return 'MicrosoftGraphOrgReaderProcessor';\n }\n\n async readLocation(\n location: LocationSpec,\n _optional: boolean,\n emit: CatalogProcessorEmit,\n ): Promise<boolean> {\n if (location.type !== 'microsoft-graph-org') {\n return false;\n }\n\n const provider = this.providers.find(p =>\n location.target.startsWith(p.target),\n );\n if (!provider) {\n throw new Error(\n `There is no Microsoft Graph Org provider that matches ${location.target}. Please add a configuration entry for it under catalog.processors.microsoftGraphOrg.providers.`,\n );\n }\n\n // Read out all the raw data\n const startTimestamp = Date.now();\n this.logger.info('Reading Microsoft Graph users and groups');\n\n // We create a client each time as we need one that matches the specific provider\n const client = MicrosoftGraphClient.create(provider);\n const { users, groups } = await readMicrosoftGraphOrg(\n client,\n provider.tenantId,\n {\n userExpand: provider.userExpand,\n userFilter: provider.userFilter,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n queryMode: provider.queryMode,\n userTransformer: this.userTransformer,\n groupTransformer: this.groupTransformer,\n organizationTransformer: this.organizationTransformer,\n logger: this.logger,\n },\n );\n\n const duration = ((Date.now() - startTimestamp) / 1000).toFixed(1);\n this.logger.debug(\n `Read ${users.length} users and ${groups.length} groups from Microsoft Graph in ${duration} seconds`,\n );\n\n // Done!\n for (const group of groups) {\n emit(processingResult.entity(location, group));\n }\n for (const user of users) {\n emit(processingResult.entity(location, user));\n }\n\n return true;\n }\n}\n"],"names":["readMicrosoftGraphConfig","MicrosoftGraphClient","readMicrosoftGraphOrg","processingResult"],"mappings":";;;;;;;;;;;;;;;;;;;AAwCO,MAAM,gCAA6D,CAAA;AAAA,EAuBxE,YAAY,OAMT,EAAA;AA5BH,IAAiB,aAAA,CAAA,IAAA,EAAA,WAAA,CAAA,CAAA;AACjB,IAAiB,aAAA,CAAA,IAAA,EAAA,QAAA,CAAA,CAAA;AACjB,IAAiB,aAAA,CAAA,IAAA,EAAA,iBAAA,CAAA,CAAA;AACjB,IAAiB,aAAA,CAAA,IAAA,EAAA,kBAAA,CAAA,CAAA;AACjB,IAAiB,aAAA,CAAA,IAAA,EAAA,yBAAA,CAAA,CAAA;AAyBf,IAAA,OAAA,CAAQ,MAAO,CAAA,IAAA;AAAA,MACb,mOAAA;AAAA,KACF,CAAA;AACA,IAAA,IAAA,CAAK,YAAY,OAAQ,CAAA,SAAA,CAAA;AACzB,IAAA,IAAA,CAAK,SAAS,OAAQ,CAAA,MAAA,CAAA;AACtB,IAAA,IAAA,CAAK,kBAAkB,OAAQ,CAAA,eAAA,CAAA;AAC/B,IAAA,IAAA,CAAK,mBAAmB,OAAQ,CAAA,gBAAA,CAAA;AAChC,IAAA,IAAA,CAAK,0BAA0B,OAAQ,CAAA,uBAAA,CAAA;AAAA,GACzC;AAAA,EA/BA,OAAO,UACL,CAAA,MAAA,EACA,OAMA,EAAA;AACA,IAAM,MAAA,CAAA,GAAI,MAAO,CAAA,iBAAA,CAAkB,sCAAsC,CAAA,CAAA;AACzE,IAAA,OAAO,IAAI,gCAAiC,CAAA;AAAA,MAC1C,GAAG,OAAA;AAAA,MACH,SAAW,EAAA,CAAA,GAAIA,wDAAyB,CAAA,CAAC,IAAI,EAAC;AAAA,KAC/C,CAAA,CAAA;AAAA,GACH;AAAA,EAmBA,gBAA2B,GAAA;AACzB,IAAO,OAAA,kCAAA,CAAA;AAAA,GACT;AAAA,EAEA,MAAM,YAAA,CACJ,QACA,EAAA,SAAA,EACA,IACkB,EAAA;AAClB,IAAI,IAAA,QAAA,CAAS,SAAS,qBAAuB,EAAA;AAC3C,MAAO,OAAA,KAAA,CAAA;AAAA,KACT;AAEA,IAAM,MAAA,QAAA,GAAW,KAAK,SAAU,CAAA,IAAA;AAAA,MAAK,CACnC,CAAA,KAAA,QAAA,CAAS,MAAO,CAAA,UAAA,CAAW,EAAE,MAAM,CAAA;AAAA,KACrC,CAAA;AACA,IAAA,IAAI,CAAC,QAAU,EAAA;AACb,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,sDAAA,EAAyD,SAAS,MAAM,CAAA,+FAAA,CAAA;AAAA,OAC1E,CAAA;AAAA,KACF;AAGA,IAAM,MAAA,cAAA,GAAiB,KAAK,GAAI,EAAA,CAAA;AAChC,IAAK,IAAA,CAAA,MAAA,CAAO,KAAK,0CAA0C,CAAA,CAAA;AAG3D,IAAM,MAAA,MAAA,GAASC,oDAAqB,CAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AACnD,IAAA,MAAM,EAAE,KAAA,EAAO,MAAO,EAAA,GAAI,MAAMC,qDAAA;AAAA,MAC9B,MAAA;AAAA,MACA,QAAS,CAAA,QAAA;AAAA,MACT;AAAA,QACE,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,YAAY,QAAS,CAAA,UAAA;AAAA,QACrB,gBAAgB,QAAS,CAAA,cAAA;AAAA,QACzB,uBAAuB,QAAS,CAAA,qBAAA;AAAA,QAChC,uBAAuB,QAAS,CAAA,qBAAA;AAAA,QAChC,aAAa,QAAS,CAAA,WAAA;AAAA,QACtB,aAAa,QAAS,CAAA,WAAA;AAAA,QACtB,aAAa,QAAS,CAAA,WAAA;AAAA,QACtB,aAAa,QAAS,CAAA,WAAA;AAAA,QACtB,WAAW,QAAS,CAAA,SAAA;AAAA,QACpB,iBAAiB,IAAK,CAAA,eAAA;AAAA,QACtB,kBAAkB,IAAK,CAAA,gBAAA;AAAA,QACvB,yBAAyB,IAAK,CAAA,uBAAA;AAAA,QAC9B,QAAQ,IAAK,CAAA,MAAA;AAAA,OACf;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,aAAa,IAAK,CAAA,GAAA,KAAQ,cAAkB,IAAA,GAAA,EAAM,QAAQ,CAAC,CAAA,CAAA;AACjE,IAAA,IAAA,CAAK,MAAO,CAAA,KAAA;AAAA,MACV,QAAQ,KAAM,CAAA,MAAM,cAAc,MAAO,CAAA,MAAM,mCAAmC,QAAQ,CAAA,QAAA,CAAA;AAAA,KAC5F,CAAA;AAGA,IAAA,KAAA,MAAW,SAAS,MAAQ,EAAA;AAC1B,MAAA,IAAA,CAAKC,kCAAiB,CAAA,MAAA,CAAO,QAAU,EAAA,KAAK,CAAC,CAAA,CAAA;AAAA,KAC/C;AACA,IAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,MAAA,IAAA,CAAKA,kCAAiB,CAAA,MAAA,CAAO,QAAU,EAAA,IAAI,CAAC,CAAA,CAAA;AAAA,KAC9C;AAEA,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AACF;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/processors/MicrosoftGraphOrgReaderProcessor.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Config } from '@backstage/config';\nimport {\n CatalogProcessor,\n CatalogProcessorEmit,\n processingResult,\n} from '@backstage/plugin-catalog-node';\nimport { LocationSpec } from '@backstage/plugin-catalog-common';\nimport {\n GroupTransformer,\n MicrosoftGraphClient,\n MicrosoftGraphProviderConfig,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { LoggerService } from '@backstage/backend-plugin-api';\n\n/**\n * Extracts teams and users out of the Microsoft Graph API.\n *\n * @public\n * @deprecated Use the MicrosoftGraphOrgEntityProvider instead.\n */\nexport class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor {\n private readonly providers: MicrosoftGraphProviderConfig[];\n private readonly logger: LoggerService;\n private readonly userTransformer?: UserTransformer;\n private readonly groupTransformer?: GroupTransformer;\n private readonly organizationTransformer?: OrganizationTransformer;\n\n static fromConfig(\n config: Config,\n options: {\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n },\n ) {\n const c = config.getOptionalConfig('catalog.processors.microsoftGraphOrg');\n return new MicrosoftGraphOrgReaderProcessor({\n ...options,\n providers: c ? readMicrosoftGraphConfig(c) : [],\n });\n }\n\n constructor(options: {\n providers: MicrosoftGraphProviderConfig[];\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n }) {\n options.logger.warn(\n 'MicrosoftGraphOrgReaderProcessor is deprecated. Please use MicrosoftGraphOrgEntityProvider instead. More info at https://github.com/backstage/backstage/blob/master/plugins/catalog-backend-module-msgraph/CHANGELOG.md#040-next1',\n );\n this.providers = options.providers;\n this.logger = options.logger;\n this.userTransformer = options.userTransformer;\n this.groupTransformer = options.groupTransformer;\n this.organizationTransformer = options.organizationTransformer;\n }\n\n getProcessorName(): string {\n return 'MicrosoftGraphOrgReaderProcessor';\n }\n\n async readLocation(\n location: LocationSpec,\n _optional: boolean,\n emit: CatalogProcessorEmit,\n ): Promise<boolean> {\n if (location.type !== 'microsoft-graph-org') {\n return false;\n }\n\n const provider = this.providers.find(p =>\n location.target.startsWith(p.target),\n );\n if (!provider) {\n throw new Error(\n `There is no Microsoft Graph Org provider that matches ${location.target}. Please add a configuration entry for it under catalog.processors.microsoftGraphOrg.providers.`,\n );\n }\n\n // Read out all the raw data\n const startTimestamp = Date.now();\n this.logger.info('Reading Microsoft Graph users and groups');\n\n // We create a client each time as we need one that matches the specific provider\n const client = MicrosoftGraphClient.create(provider);\n const { users, groups } = await readMicrosoftGraphOrg(\n client,\n provider.tenantId,\n {\n userExpand: provider.userExpand,\n userFilter: provider.userFilter,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n queryMode: provider.queryMode,\n userTransformer: this.userTransformer,\n groupTransformer: this.groupTransformer,\n organizationTransformer: this.organizationTransformer,\n logger: this.logger,\n },\n );\n\n const duration = ((Date.now() - startTimestamp) / 1000).toFixed(1);\n this.logger.debug(\n `Read ${users.length} users and ${groups.length} groups from Microsoft Graph in ${duration} seconds`,\n );\n\n // Done!\n for (const group of groups) {\n emit(processingResult.entity(location, group));\n }\n for (const user of users) {\n emit(processingResult.entity(location, user));\n }\n\n return true;\n }\n}\n"],"names":["readMicrosoftGraphConfig","MicrosoftGraphClient","readMicrosoftGraphOrg","processingResult"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-backend-module-msgraph",
3
- "version": "0.5.26-next.2",
3
+ "version": "0.5.27-next.0",
4
4
  "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph",
5
5
  "backstage": {
6
6
  "role": "backend-plugin-module"
@@ -49,13 +49,13 @@
49
49
  },
50
50
  "dependencies": {
51
51
  "@azure/identity": "^4.0.0",
52
- "@backstage/backend-common": "^0.22.0-next.2",
53
- "@backstage/backend-plugin-api": "^0.6.18-next.1",
54
- "@backstage/backend-tasks": "^0.5.23-next.1",
55
- "@backstage/catalog-model": "^1.5.0-next.0",
52
+ "@backstage/backend-common": "^0.22.1-next.0",
53
+ "@backstage/backend-plugin-api": "^0.6.19-next.0",
54
+ "@backstage/backend-tasks": "^0.5.24-next.0",
55
+ "@backstage/catalog-model": "^1.5.0",
56
56
  "@backstage/config": "^1.2.0",
57
- "@backstage/plugin-catalog-common": "^1.0.23-next.0",
58
- "@backstage/plugin-catalog-node": "^1.12.0-next.2",
57
+ "@backstage/plugin-catalog-common": "^1.0.23",
58
+ "@backstage/plugin-catalog-node": "^1.12.1-next.0",
59
59
  "@microsoft/microsoft-graph-types": "^2.6.0",
60
60
  "@types/node-fetch": "^2.5.12",
61
61
  "lodash": "^4.17.21",
@@ -65,9 +65,9 @@
65
65
  "uuid": "^9.0.0"
66
66
  },
67
67
  "devDependencies": {
68
- "@backstage/backend-common": "^0.22.0-next.2",
69
- "@backstage/backend-test-utils": "^0.3.8-next.2",
70
- "@backstage/cli": "^0.26.5-next.1",
68
+ "@backstage/backend-common": "^0.22.1-next.0",
69
+ "@backstage/backend-test-utils": "^0.3.9-next.0",
70
+ "@backstage/cli": "^0.26.6-next.0",
71
71
  "@types/lodash": "^4.14.151",
72
72
  "luxon": "^3.0.0",
73
73
  "msw": "^1.0.0"