@backstage/plugin-catalog-backend-module-msgraph 0.9.3-next.0 → 0.10.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,30 @@
1
1
  # @backstage/plugin-catalog-backend-module-msgraph
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2bd0450: **BREAKING**: Disabled user accounts are now filtered out by default. The provider automatically applies an `accountEnabled eq true` filter, combining it with any custom `user.filter` you provide. If you previously included `accountEnabled eq true` in your user filter, it is safe to remove it, but leaving it in will not cause any issues.
8
+
9
+ ### Patch Changes
10
+
11
+ - e9b78e9: Removed the `uuid` dependency and replaced usage with the built-in `crypto.randomUUID()`.
12
+ - Updated dependencies
13
+ - @backstage/catalog-model@1.9.0
14
+ - @backstage/backend-plugin-api@1.9.1
15
+ - @backstage/plugin-catalog-node@2.2.1
16
+ - @backstage/config@1.3.8
17
+ - @backstage/plugin-catalog-common@1.1.10
18
+
19
+ ## 0.9.3-next.1
20
+
21
+ ### Patch Changes
22
+
23
+ - e9b78e9: Removed the `uuid` dependency and replaced usage with the built-in `crypto.randomUUID()`.
24
+ - Updated dependencies
25
+ - @backstage/catalog-model@1.8.1-next.1
26
+ - @backstage/plugin-catalog-node@2.2.1-next.1
27
+
3
28
  ## 0.9.3-next.0
4
29
 
5
30
  ### Patch Changes
package/README.md CHANGED
@@ -52,8 +52,9 @@ catalog:
52
52
  # Optional filter for user, see Microsoft Graph API for the syntax
53
53
  # See https://docs.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0#properties
54
54
  # and for the syntax https://docs.microsoft.com/en-us/graph/query-parameters#filter-parameter
55
- # This and userGroupMemberFilter are mutually exclusive, only one can be specified
56
- filter: accountEnabled eq true and userType eq 'member'
55
+ # This is combined with the base `accountEnabled eq true` filter
56
+ # that is always applied automatically.
57
+ filter: userType eq 'member'
57
58
  # Set to false to not load user photos.
58
59
  loadPhotos: true
59
60
  # See https://docs.microsoft.com/en-us/graph/api/resources/schemaextension?view=graph-rest-1.0
@@ -64,12 +65,10 @@ catalog:
64
65
  userGroupMember:
65
66
  # Optional filter for users, use group membership to get users.
66
67
  # (Filtered groups and fetch their members.)
67
- # This and userFilter are mutually exclusive, only one can be specified
68
68
  # See https://docs.microsoft.com/en-us/graph/search-query-parameter
69
69
  filter: "displayName eq 'Backstage Users'"
70
70
  # Optional search for users, use group membership to get users.
71
71
  # (Search for groups and fetch their members.)
72
- # This and userFilter are mutually exclusive, only one can be specified
73
72
  search: '"description:One" AND ("displayName:Video" OR "displayName:Drive")'
74
73
  # Optional /groups by default but allow to query groups from different msgraph endpoints
75
74
  path: /groups
@@ -102,9 +101,7 @@ catalog:
102
101
  initialDelay: { seconds: 15},
103
102
  ```
104
103
 
105
- `user.filter` and `userGroupMember.filter` are mutually exclusive, only one can be provided. If both are provided, an error will be thrown.
106
-
107
- By default, all users are loaded. If you want to filter users based on their attributes, use `user.filter`. `userGroupMember.filter` can be used if you want to load users based on their group membership.
104
+ By default, all enabled users are loaded (disabled accounts are automatically filtered out). If you want to further filter users based on their attributes, use `user.filter`. `userGroupMember.filter` can be used if you want to load users based on their group membership.
108
105
 
109
106
  3. The package is not installed by default, therefore you have to add a
110
107
  dependency to `@backstage/plugin-catalog-backend-module-msgraph` to your
package/config.d.ts CHANGED
@@ -60,8 +60,9 @@ export interface Config {
60
60
 
61
61
  /**
62
62
  * The filter to apply to extract users.
63
+ * Combined with the base `accountEnabled eq true` filter.
63
64
  *
64
- * E.g. "accountEnabled eq true and userType eq 'member'"
65
+ * E.g. "userType eq 'member'"
65
66
  */
66
67
  userFilter?: string;
67
68
  /**
@@ -162,8 +163,9 @@ export interface Config {
162
163
  expand?: string;
163
164
  /**
164
165
  * The filter to apply to extract users.
166
+ * Combined with the base `accountEnabled eq true` filter
165
167
  *
166
- * E.g. "accountEnabled eq true and userType eq 'member'"
168
+ * E.g. "userType eq 'member'"
167
169
  */
168
170
  filter?: string;
169
171
  /**
@@ -295,8 +297,9 @@ export interface Config {
295
297
  expand?: string;
296
298
  /**
297
299
  * The filter to apply to extract users.
300
+ * Combined with the base `accountEnabled eq true` filter
298
301
  *
299
- * E.g. "accountEnabled eq true and userType eq 'member'"
302
+ * E.g. "userType eq 'member'"
300
303
  */
301
304
  filter?: string;
302
305
  /**
package/dist/index.d.ts CHANGED
@@ -43,9 +43,10 @@ type MicrosoftGraphProviderConfig = {
43
43
  */
44
44
  clientSecret?: string;
45
45
  /**
46
- * The filter to apply to extract users.
46
+ * The filter to apply to extract users. This is combined with the base
47
+ * `accountEnabled eq true` filter that is always applied automatically.
47
48
  *
48
- * E.g. "accountEnabled eq true and userType eq 'member'"
49
+ * E.g. "userType eq 'member'"
49
50
  */
50
51
  userFilter?: string;
51
52
  /**
@@ -18,7 +18,9 @@ function readMicrosoftGraphConfig(config) {
18
18
  const clientId = providerConfig.getOptionalString("clientId");
19
19
  const clientSecret = providerConfig.getOptionalString("clientSecret");
20
20
  const userExpand = providerConfig.getOptionalString("userExpand");
21
- const userFilter = providerConfig.getOptionalString("userFilter");
21
+ const userFilter = buildUserFilter(
22
+ providerConfig.getOptionalString("userFilter")
23
+ );
22
24
  const userSelect = providerConfig.getOptionalStringArray("userSelect");
23
25
  const userGroupMemberFilter = providerConfig.getOptionalString(
24
26
  "userGroupMemberFilter"
@@ -29,16 +31,6 @@ function readMicrosoftGraphConfig(config) {
29
31
  const groupExpand = providerConfig.getOptionalString("groupExpand");
30
32
  const groupFilter = providerConfig.getOptionalString("groupFilter");
31
33
  const groupSearch = providerConfig.getOptionalString("groupSearch");
32
- if (userFilter && userGroupMemberFilter) {
33
- throw new Error(
34
- `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`
35
- );
36
- }
37
- if (userFilter && userGroupMemberSearch) {
38
- throw new Error(
39
- `userGroupMemberSearch cannot be specified when userFilter is defined.`
40
- );
41
- }
42
34
  const groupSelect = providerConfig.getOptionalStringArray("groupSelect");
43
35
  const queryMode = providerConfig.getOptionalString("queryMode");
44
36
  if (queryMode !== void 0 && queryMode !== "basic" && queryMode !== "advanced") {
@@ -100,7 +92,7 @@ function readProviderConfig(id, config) {
100
92
  const clientId = config.getOptionalString("clientId");
101
93
  const clientSecret = config.getOptionalString("clientSecret");
102
94
  const userExpand = config.getOptionalString("user.expand");
103
- const userFilter = config.getOptionalString("user.filter");
95
+ const userFilter = buildUserFilter(config.getOptionalString("user.filter"));
104
96
  const userSelect = config.getOptionalStringArray("user.select");
105
97
  const userPath = config.getOptionalString("user.path") ?? "users";
106
98
  const loadUserPhotos = config.getOptionalBoolean("user.loadPhotos");
@@ -123,16 +115,6 @@ function readProviderConfig(id, config) {
123
115
  "userGroupMember.search"
124
116
  );
125
117
  const userGroupMemberPath = config.getOptionalString("userGroupMember.path");
126
- if (userFilter && userGroupMemberFilter) {
127
- throw new Error(
128
- `userFilter and userGroupMemberFilter are mutually exclusive, only one can be specified.`
129
- );
130
- }
131
- if (userFilter && userGroupMemberSearch) {
132
- throw new Error(
133
- `userGroupMemberSearch cannot be specified when userFilter is defined.`
134
- );
135
- }
136
118
  if (clientId && !clientSecret) {
137
119
  throw new Error(`clientSecret must be provided when clientId is defined.`);
138
120
  }
@@ -167,6 +149,13 @@ function readProviderConfig(id, config) {
167
149
  schedule
168
150
  };
169
151
  }
152
+ function buildUserFilter(rawFilter) {
153
+ const base = "accountEnabled eq true";
154
+ if (rawFilter) {
155
+ return `${base} and (${rawFilter})`;
156
+ }
157
+ return base;
158
+ }
170
159
 
171
160
  exports.readMicrosoftGraphConfig = readMicrosoftGraphConfig;
172
161
  exports.readProviderConfig = readProviderConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"config.cjs.js","sources":["../../src/microsoftGraph/config.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 SchedulerServiceTaskScheduleDefinition,\n readSchedulerServiceTaskScheduleDefinitionFromConfig,\n} from '@backstage/backend-plugin-api';\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 /**\n * The path to the users endpoint. Defaults to \"/users\".\n *\n * E.g. \"/users\"\n */\n userPath?: 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 /**\n * The path to the groups endpoint. Defaults to \"/groups\".\n *\n * E.g. \"/groups\"\n */\n userGroupMemberPath?: string;\n\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 * The path to the groups endpoint. Defaults to \"/groups\".\n *\n * E.g. \"/groups\"\n */\n groupPath?: string;\n\n /**\n * Whether to ingest groups that are members of the found/filtered/searched groups.\n * Default value is `false`.\n */\n groupIncludeSubGroups?: boolean;\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?: SchedulerServiceTaskScheduleDefinition;\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 userPath = config.getOptionalString('user.path') ?? 'users';\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 const groupPath = config.getOptionalString('group.path') ?? 'groups';\n const groupIncludeSubGroups = config.getOptionalBoolean(\n 'group.includeSubGroups',\n );\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 const userGroupMemberPath = config.getOptionalString('userGroupMember.path');\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 ? readSchedulerServiceTaskScheduleDefinitionFromConfig(\n config.getConfig('schedule'),\n )\n : undefined;\n\n return {\n id,\n target,\n authority,\n clientId,\n clientSecret,\n tenantId,\n userExpand,\n userFilter,\n userSelect,\n userPath,\n loadUserPhotos,\n groupExpand,\n groupFilter,\n groupSearch,\n groupSelect,\n groupPath,\n groupIncludeSubGroups,\n queryMode,\n userGroupMemberFilter,\n userGroupMemberSearch,\n userGroupMemberPath,\n schedule,\n };\n}\n"],"names":["trimEnd","readSchedulerServiceTaskScheduleDefinitionFromConfig"],"mappings":"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"}
1
+ {"version":3,"file":"config.cjs.js","sources":["../../src/microsoftGraph/config.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 SchedulerServiceTaskScheduleDefinition,\n readSchedulerServiceTaskScheduleDefinitionFromConfig,\n} from '@backstage/backend-plugin-api';\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. This is combined with the base\n * `accountEnabled eq true` filter that is always applied automatically.\n *\n * E.g. \"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 /**\n * The path to the users endpoint. Defaults to \"/users\".\n *\n * E.g. \"/users\"\n */\n userPath?: 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 /**\n * The path to the groups endpoint. Defaults to \"/groups\".\n *\n * E.g. \"/groups\"\n */\n userGroupMemberPath?: string;\n\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 * The path to the groups endpoint. Defaults to \"/groups\".\n *\n * E.g. \"/groups\"\n */\n groupPath?: string;\n\n /**\n * Whether to ingest groups that are members of the found/filtered/searched groups.\n * Default value is `false`.\n */\n groupIncludeSubGroups?: boolean;\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?: SchedulerServiceTaskScheduleDefinition;\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 = buildUserFilter(\n providerConfig.getOptionalString('userFilter'),\n );\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 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 = buildUserFilter(config.getOptionalString('user.filter'));\n const userSelect = config.getOptionalStringArray('user.select');\n const userPath = config.getOptionalString('user.path') ?? 'users';\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 const groupPath = config.getOptionalString('group.path') ?? 'groups';\n const groupIncludeSubGroups = config.getOptionalBoolean(\n 'group.includeSubGroups',\n );\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 const userGroupMemberPath = config.getOptionalString('userGroupMember.path');\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 ? readSchedulerServiceTaskScheduleDefinitionFromConfig(\n config.getConfig('schedule'),\n )\n : undefined;\n\n return {\n id,\n target,\n authority,\n clientId,\n clientSecret,\n tenantId,\n userExpand,\n userFilter,\n userSelect,\n userPath,\n loadUserPhotos,\n groupExpand,\n groupFilter,\n groupSearch,\n groupSelect,\n groupPath,\n groupIncludeSubGroups,\n queryMode,\n userGroupMemberFilter,\n userGroupMemberSearch,\n userGroupMemberPath,\n schedule,\n };\n}\n\nfunction buildUserFilter(rawFilter: string | undefined): string {\n const base = 'accountEnabled eq true';\n if (rawFilter) {\n return `${base} and (${rawFilter})`;\n }\n return base;\n}\n"],"names":["trimEnd","readSchedulerServiceTaskScheduleDefinitionFromConfig"],"mappings":"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"}
@@ -2,32 +2,12 @@
2
2
 
3
3
  var catalogModel = require('@backstage/catalog-model');
4
4
  var lodash = require('lodash');
5
- var uuid = require('uuid');
5
+ var node_crypto = require('node:crypto');
6
6
  var client = require('../microsoftGraph/client.cjs.js');
7
7
  var config = require('../microsoftGraph/config.cjs.js');
8
8
  var constants = require('../microsoftGraph/constants.cjs.js');
9
9
  var read = require('../microsoftGraph/read.cjs.js');
10
10
 
11
- function _interopNamespaceCompat(e) {
12
- if (e && typeof e === 'object' && 'default' in e) return e;
13
- var n = Object.create(null);
14
- if (e) {
15
- Object.keys(e).forEach(function (k) {
16
- if (k !== 'default') {
17
- var d = Object.getOwnPropertyDescriptor(e, k);
18
- Object.defineProperty(n, k, d.get ? d : {
19
- enumerable: true,
20
- get: function () { return e[k]; }
21
- });
22
- }
23
- });
24
- }
25
- n.default = e;
26
- return Object.freeze(n);
27
- }
28
-
29
- var uuid__namespace = /*#__PURE__*/_interopNamespaceCompat(uuid);
30
-
31
11
  class MicrosoftGraphOrgEntityProvider {
32
12
  connection;
33
13
  scheduleFn;
@@ -188,7 +168,7 @@ class MicrosoftGraphOrgEntityProvider {
188
168
  const logger = this.options.logger.child({
189
169
  class: MicrosoftGraphOrgEntityProvider.prototype.constructor.name,
190
170
  taskId: id,
191
- taskInstanceId: uuid__namespace.v4()
171
+ taskInstanceId: node_crypto.randomUUID()
192
172
  });
193
173
  try {
194
174
  await this.read({ logger, signal: abortSignal });
@@ -1 +1 @@
1
- {"version":3,"file":"MicrosoftGraphOrgEntityProvider.cjs.js","sources":["../../src/processors/MicrosoftGraphOrgEntityProvider.ts"],"sourcesContent":["/*\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 {\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 ProviderConfigTransformer,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { readProviderConfigs } from '../microsoftGraph/config';\nimport {\n LoggerService,\n SchedulerService,\n SchedulerServiceTaskRunner,\n} 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-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule?: 'manual' | SchedulerServiceTaskRunner;\n\n /**\n * Scheduler used to schedule refreshes based on\n * the schedule config.\n */\n scheduler?: SchedulerService;\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 * The function that transforms provider config dynamically.\n */\n providerConfigTransformer?:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>;\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-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule: 'manual' | SchedulerServiceTaskRunner;\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 * The function that transforms provider config dynamically.\n */\n providerConfigTransformer?: ProviderConfigTransformer;\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 providerConfigTransformer: getTransformer(\n providerConfig.id,\n options.providerConfigTransformer,\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 providerConfigTransformer: options.providerConfigTransformer,\n logger,\n provider,\n });\n\n if (options.schedule !== 'manual') {\n result.schedule(options.schedule);\n }\n\n return result;\n }\n\n private options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n };\n\n constructor(options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n }) {\n this.options = options;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */\n getProviderName() {\n return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-node#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; signal?: AbortSignal }) {\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.providerConfigTransformer\n ? await this.options.providerConfigTransformer(this.options.provider)\n : this.options.provider;\n const { markReadComplete } = trackProgress(logger);\n const client = MicrosoftGraphClient.create(this.options.provider);\n\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 userPath: provider.userPath,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n userGroupMemberPath: provider.userGroupMemberPath,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n groupPath: provider.groupPath,\n groupIncludeSubGroups: provider.groupIncludeSubGroups,\n queryMode: provider.queryMode,\n groupTransformer: this.options.groupTransformer,\n userTransformer: this.options.userTransformer,\n organizationTransformer: this.options.organizationTransformer,\n logger: logger,\n signal: options?.signal,\n },\n );\n\n const { markCommitComplete } = markReadComplete({\n users,\n groups,\n tenantId: provider.tenantId,\n });\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(groups.length, users.length, provider.tenantId);\n }\n\n private schedule(taskRunner: SchedulerServiceTaskRunner) {\n this.scheduleFn = async () => {\n const id = `${this.getProviderName()}:refresh`;\n await taskRunner.run({\n id,\n fn: async (abortSignal: AbortSignal) => {\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, signal: abortSignal });\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n logger.debug(\n `${this.getProviderName()} refresh aborted due to shutdown`,\n );\n return;\n }\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: {\n users: unknown[];\n groups: unknown[];\n tenantId: string;\n }) {\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 readDuration,\n tenantId: read.tenantId,\n usersCount: read.users.length,\n groupsCount: read.groups.length,\n });\n return { markCommitComplete };\n }\n\n function markCommitComplete(\n groupsCount: number,\n usersCount: number,\n tenantId: string,\n ) {\n const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n logger.info(`Committed ${summary} in ${commitDuration} seconds.`, {\n commitDuration,\n tenantId,\n usersCount,\n groupsCount,\n });\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":["readProviderConfigs","config","readMicrosoftGraphConfig","client","MicrosoftGraphClient","readMicrosoftGraphOrg","uuid","MICROSOFT_GRAPH_USER_ID_ANNOTATION","MICROSOFT_GRAPH_GROUP_ID_ANNOTATION","MICROSOFT_GRAPH_TENANT_ID_ANNOTATION","merge","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION"],"mappings":"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"}
1
+ {"version":3,"file":"MicrosoftGraphOrgEntityProvider.cjs.js","sources":["../../src/processors/MicrosoftGraphOrgEntityProvider.ts"],"sourcesContent":["/*\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 {\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 { randomUUID } from 'node:crypto';\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 ProviderConfigTransformer,\n OrganizationTransformer,\n readMicrosoftGraphConfig,\n readMicrosoftGraphOrg,\n UserTransformer,\n} from '../microsoftGraph';\nimport { readProviderConfigs } from '../microsoftGraph/config';\nimport {\n LoggerService,\n SchedulerService,\n SchedulerServiceTaskRunner,\n} 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-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule?: 'manual' | SchedulerServiceTaskRunner;\n\n /**\n * Scheduler used to schedule refreshes based on\n * the schedule config.\n */\n scheduler?: SchedulerService;\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 * The function that transforms provider config dynamically.\n */\n providerConfigTransformer?:\n | ProviderConfigTransformer\n | Record<string, ProviderConfigTransformer>;\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-plugin-api#SchedulerService.createScheduledTaskRunner}\n * to enable automatic scheduling of tasks.\n */\n schedule: 'manual' | SchedulerServiceTaskRunner;\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 * The function that transforms provider config dynamically.\n */\n providerConfigTransformer?: ProviderConfigTransformer;\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 providerConfigTransformer: getTransformer(\n providerConfig.id,\n options.providerConfigTransformer,\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 providerConfigTransformer: options.providerConfigTransformer,\n logger,\n provider,\n });\n\n if (options.schedule !== 'manual') {\n result.schedule(options.schedule);\n }\n\n return result;\n }\n\n private options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n };\n\n constructor(options: {\n id: string;\n provider: MicrosoftGraphProviderConfig;\n logger: LoggerService;\n userTransformer?: UserTransformer;\n groupTransformer?: GroupTransformer;\n organizationTransformer?: OrganizationTransformer;\n providerConfigTransformer?: ProviderConfigTransformer;\n }) {\n this.options = options;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-node#EntityProvider.getProviderName} */\n getProviderName() {\n return `MicrosoftGraphOrgEntityProvider:${this.options.id}`;\n }\n\n /** {@inheritdoc @backstage/plugin-catalog-node#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; signal?: AbortSignal }) {\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.providerConfigTransformer\n ? await this.options.providerConfigTransformer(this.options.provider)\n : this.options.provider;\n const { markReadComplete } = trackProgress(logger);\n const client = MicrosoftGraphClient.create(this.options.provider);\n\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 userPath: provider.userPath,\n loadUserPhotos: provider.loadUserPhotos,\n userGroupMemberFilter: provider.userGroupMemberFilter,\n userGroupMemberSearch: provider.userGroupMemberSearch,\n userGroupMemberPath: provider.userGroupMemberPath,\n groupExpand: provider.groupExpand,\n groupFilter: provider.groupFilter,\n groupSearch: provider.groupSearch,\n groupSelect: provider.groupSelect,\n groupPath: provider.groupPath,\n groupIncludeSubGroups: provider.groupIncludeSubGroups,\n queryMode: provider.queryMode,\n groupTransformer: this.options.groupTransformer,\n userTransformer: this.options.userTransformer,\n organizationTransformer: this.options.organizationTransformer,\n logger: logger,\n signal: options?.signal,\n },\n );\n\n const { markCommitComplete } = markReadComplete({\n users,\n groups,\n tenantId: provider.tenantId,\n });\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(groups.length, users.length, provider.tenantId);\n }\n\n private schedule(taskRunner: SchedulerServiceTaskRunner) {\n this.scheduleFn = async () => {\n const id = `${this.getProviderName()}:refresh`;\n await taskRunner.run({\n id,\n fn: async (abortSignal: AbortSignal) => {\n const logger = this.options.logger.child({\n class: MicrosoftGraphOrgEntityProvider.prototype.constructor.name,\n taskId: id,\n taskInstanceId: randomUUID(),\n });\n\n try {\n await this.read({ logger, signal: abortSignal });\n } catch (error) {\n if (error instanceof Error && error.name === 'AbortError') {\n logger.debug(\n `${this.getProviderName()} refresh aborted due to shutdown`,\n );\n return;\n }\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: {\n users: unknown[];\n groups: unknown[];\n tenantId: string;\n }) {\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 readDuration,\n tenantId: read.tenantId,\n usersCount: read.users.length,\n groupsCount: read.groups.length,\n });\n return { markCommitComplete };\n }\n\n function markCommitComplete(\n groupsCount: number,\n usersCount: number,\n tenantId: string,\n ) {\n const commitDuration = ((Date.now() - timestamp) / 1000).toFixed(1);\n logger.info(`Committed ${summary} in ${commitDuration} seconds.`, {\n commitDuration,\n tenantId,\n usersCount,\n groupsCount,\n });\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":["readProviderConfigs","config","readMicrosoftGraphConfig","client","MicrosoftGraphClient","readMicrosoftGraphOrg","randomUUID","MICROSOFT_GRAPH_USER_ID_ANNOTATION","MICROSOFT_GRAPH_GROUP_ID_ANNOTATION","MICROSOFT_GRAPH_TENANT_ID_ANNOTATION","merge","ANNOTATION_LOCATION","ANNOTATION_ORIGIN_LOCATION"],"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.9.3-next.0",
3
+ "version": "0.10.0",
4
4
  "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph",
5
5
  "backstage": {
6
6
  "role": "backend-plugin-module",
@@ -66,20 +66,19 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@azure/identity": "^4.0.0",
69
- "@backstage/backend-plugin-api": "1.9.1-next.0",
70
- "@backstage/catalog-model": "1.8.1-next.0",
71
- "@backstage/config": "1.3.8-next.0",
72
- "@backstage/plugin-catalog-common": "1.1.10-next.0",
73
- "@backstage/plugin-catalog-node": "2.2.1-next.0",
69
+ "@backstage/backend-plugin-api": "^1.9.1",
70
+ "@backstage/catalog-model": "^1.9.0",
71
+ "@backstage/config": "^1.3.8",
72
+ "@backstage/plugin-catalog-common": "^1.1.10",
73
+ "@backstage/plugin-catalog-node": "^2.2.1",
74
74
  "@microsoft/microsoft-graph-types": "^2.6.0",
75
75
  "lodash": "^4.17.21",
76
76
  "p-limit": "^3.0.2",
77
- "qs": "^6.9.4",
78
- "uuid": "^11.0.0"
77
+ "qs": "^6.9.4"
79
78
  },
80
79
  "devDependencies": {
81
- "@backstage/backend-test-utils": "1.11.3-next.0",
82
- "@backstage/cli": "0.36.2-next.0",
80
+ "@backstage/backend-test-utils": "^1.11.3",
81
+ "@backstage/cli": "^0.36.2",
83
82
  "@types/lodash": "^4.14.151",
84
83
  "msw": "^1.0.0"
85
84
  },