@or-sdk/authorizer 0.24.17 → 0.24.18

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.
Files changed (133) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +12 -32
  3. package/dist/cjs/Basic/BasicCollection.js +260 -27
  4. package/dist/cjs/Basic/BasicCollection.js.map +1 -1
  5. package/dist/cjs/Basic/index.js +21 -0
  6. package/dist/cjs/Basic/index.js.map +1 -0
  7. package/dist/cjs/Basic/utils/createAuthKey.js +5 -1
  8. package/dist/cjs/Basic/utils/createAuthKey.js.map +1 -1
  9. package/dist/cjs/OAuth/OAuth.js +114 -131
  10. package/dist/cjs/OAuth/OAuth.js.map +1 -1
  11. package/dist/cjs/OAuth/index.js +21 -0
  12. package/dist/cjs/OAuth/index.js.map +1 -0
  13. package/dist/cjs/OAuth/types.js.map +1 -1
  14. package/dist/cjs/OAuth/utils/createAuthKey.js +5 -1
  15. package/dist/cjs/OAuth/utils/createAuthKey.js.map +1 -1
  16. package/dist/cjs/OAuth/utils/createOAuthHelper.js +379 -0
  17. package/dist/cjs/OAuth/utils/createOAuthHelper.js.map +1 -0
  18. package/dist/cjs/OAuthCollection/OAuthCollection.js +312 -0
  19. package/dist/cjs/OAuthCollection/OAuthCollection.js.map +1 -0
  20. package/dist/cjs/OAuthCollection/index.js +21 -0
  21. package/dist/cjs/OAuthCollection/index.js.map +1 -0
  22. package/dist/cjs/Token/TokenCollection.js +237 -26
  23. package/dist/cjs/Token/TokenCollection.js.map +1 -1
  24. package/dist/cjs/Token/index.js +21 -0
  25. package/dist/cjs/Token/index.js.map +1 -0
  26. package/dist/cjs/Token/utils/createAuthKey.js +5 -1
  27. package/dist/cjs/Token/utils/createAuthKey.js.map +1 -1
  28. package/dist/cjs/constants.js +2 -1
  29. package/dist/cjs/constants.js.map +1 -1
  30. package/dist/cjs/index.js +9 -13
  31. package/dist/cjs/index.js.map +1 -1
  32. package/dist/esm/Basic/BasicCollection.js +183 -23
  33. package/dist/esm/Basic/BasicCollection.js.map +1 -1
  34. package/dist/esm/Basic/index.js +3 -0
  35. package/dist/esm/Basic/index.js.map +1 -0
  36. package/dist/esm/Basic/utils/createAuthKey.js +3 -0
  37. package/dist/esm/Basic/utils/createAuthKey.js.map +1 -1
  38. package/dist/esm/OAuth/OAuth.js +73 -107
  39. package/dist/esm/OAuth/OAuth.js.map +1 -1
  40. package/dist/esm/OAuth/index.js +3 -0
  41. package/dist/esm/OAuth/index.js.map +1 -0
  42. package/dist/esm/OAuth/types.js.map +1 -1
  43. package/dist/esm/OAuth/utils/createAuthKey.js +3 -0
  44. package/dist/esm/OAuth/utils/createAuthKey.js.map +1 -1
  45. package/dist/esm/OAuth/utils/createOAuthHelper.js +262 -0
  46. package/dist/esm/OAuth/utils/createOAuthHelper.js.map +1 -0
  47. package/dist/esm/OAuthCollection/OAuthCollection.js +190 -0
  48. package/dist/esm/OAuthCollection/OAuthCollection.js.map +1 -0
  49. package/dist/esm/OAuthCollection/index.js +3 -0
  50. package/dist/esm/OAuthCollection/index.js.map +1 -0
  51. package/dist/esm/Token/TokenCollection.js +161 -23
  52. package/dist/esm/Token/TokenCollection.js.map +1 -1
  53. package/dist/esm/Token/index.js +3 -0
  54. package/dist/esm/Token/index.js.map +1 -0
  55. package/dist/esm/Token/utils/createAuthKey.js +3 -0
  56. package/dist/esm/Token/utils/createAuthKey.js.map +1 -1
  57. package/dist/esm/constants.js +1 -0
  58. package/dist/esm/constants.js.map +1 -1
  59. package/dist/esm/index.js +4 -6
  60. package/dist/esm/index.js.map +1 -1
  61. package/dist/types/Basic/BasicCollection.d.ts +20 -8
  62. package/dist/types/Basic/BasicCollection.d.ts.map +1 -1
  63. package/dist/types/Basic/index.d.ts +3 -0
  64. package/dist/types/Basic/index.d.ts.map +1 -0
  65. package/dist/types/Basic/types.d.ts +19 -8
  66. package/dist/types/Basic/types.d.ts.map +1 -1
  67. package/dist/types/Basic/utils/createAuthKey.d.ts +1 -0
  68. package/dist/types/Basic/utils/createAuthKey.d.ts.map +1 -1
  69. package/dist/types/OAuth/OAuth.d.ts +9 -6
  70. package/dist/types/OAuth/OAuth.d.ts.map +1 -1
  71. package/dist/types/OAuth/index.d.ts +3 -0
  72. package/dist/types/OAuth/index.d.ts.map +1 -0
  73. package/dist/types/OAuth/types.d.ts +93 -9
  74. package/dist/types/OAuth/types.d.ts.map +1 -1
  75. package/dist/types/OAuth/utils/createAuthKey.d.ts +1 -0
  76. package/dist/types/OAuth/utils/createAuthKey.d.ts.map +1 -1
  77. package/dist/types/OAuth/utils/createOAuthHelper.d.ts +33 -0
  78. package/dist/types/OAuth/utils/createOAuthHelper.d.ts.map +1 -0
  79. package/dist/types/OAuthCollection/OAuthCollection.d.ts +27 -0
  80. package/dist/types/OAuthCollection/OAuthCollection.d.ts.map +1 -0
  81. package/dist/types/OAuthCollection/index.d.ts +3 -0
  82. package/dist/types/OAuthCollection/index.d.ts.map +1 -0
  83. package/dist/types/Token/TokenCollection.d.ts +12 -8
  84. package/dist/types/Token/TokenCollection.d.ts.map +1 -1
  85. package/dist/types/Token/index.d.ts +3 -0
  86. package/dist/types/Token/index.d.ts.map +1 -0
  87. package/dist/types/Token/types.d.ts +16 -0
  88. package/dist/types/Token/types.d.ts.map +1 -1
  89. package/dist/types/Token/utils/createAuthKey.d.ts +1 -0
  90. package/dist/types/Token/utils/createAuthKey.d.ts.map +1 -1
  91. package/dist/types/constants.d.ts +1 -0
  92. package/dist/types/constants.d.ts.map +1 -1
  93. package/dist/types/index.d.ts +4 -6
  94. package/dist/types/index.d.ts.map +1 -1
  95. package/package.json +39 -2
  96. package/src/Basic/BasicCollection.ts +295 -32
  97. package/src/Basic/index.ts +3 -0
  98. package/src/Basic/types.ts +20 -15
  99. package/src/Basic/utils/createAuthKey.ts +4 -0
  100. package/src/OAuth/OAuth.ts +148 -174
  101. package/src/OAuth/index.ts +3 -0
  102. package/src/OAuth/types.ts +198 -13
  103. package/src/OAuth/utils/createAuthKey.ts +8 -0
  104. package/src/OAuth/utils/createOAuthHelper.ts +374 -0
  105. package/src/OAuthCollection/OAuthCollection.ts +348 -0
  106. package/src/OAuthCollection/index.ts +3 -0
  107. package/src/Token/TokenCollection.ts +258 -31
  108. package/src/Token/index.ts +3 -0
  109. package/src/Token/types.ts +17 -0
  110. package/src/Token/utils/createAuthKey.ts +4 -0
  111. package/src/constants.ts +1 -0
  112. package/src/index.ts +4 -8
  113. package/dist/cjs/Basic/BasicAuth.js +0 -162
  114. package/dist/cjs/Basic/BasicAuth.js.map +0 -1
  115. package/dist/cjs/OAuth/OAuthCollection.js +0 -138
  116. package/dist/cjs/OAuth/OAuthCollection.js.map +0 -1
  117. package/dist/cjs/Token/TokenAuth.js +0 -140
  118. package/dist/cjs/Token/TokenAuth.js.map +0 -1
  119. package/dist/esm/Basic/BasicAuth.js +0 -88
  120. package/dist/esm/Basic/BasicAuth.js.map +0 -1
  121. package/dist/esm/OAuth/OAuthCollection.js +0 -69
  122. package/dist/esm/OAuth/OAuthCollection.js.map +0 -1
  123. package/dist/esm/Token/TokenAuth.js +0 -66
  124. package/dist/esm/Token/TokenAuth.js.map +0 -1
  125. package/dist/types/Basic/BasicAuth.d.ts +0 -20
  126. package/dist/types/Basic/BasicAuth.d.ts.map +0 -1
  127. package/dist/types/OAuth/OAuthCollection.d.ts +0 -15
  128. package/dist/types/OAuth/OAuthCollection.d.ts.map +0 -1
  129. package/dist/types/Token/TokenAuth.d.ts +0 -12
  130. package/dist/types/Token/TokenAuth.d.ts.map +0 -1
  131. package/src/Basic/BasicAuth.ts +0 -129
  132. package/src/OAuth/OAuthCollection.ts +0 -118
  133. package/src/Token/TokenAuth.ts +0 -102
@@ -0,0 +1,348 @@
1
+ import { Token, List, makeList } from '@or-sdk/base';
2
+ import { KeyValueStorage } from '@or-sdk/key-value-storage';
3
+ import { Providers } from '@or-sdk/providers';
4
+ import { OAuth } from '../OAuth/OAuth';
5
+
6
+ import {
7
+ CreateOAuthInCollectionConfig,
8
+ CreateOAuthResult,
9
+ OAuthCollectionConfig,
10
+ OAuthApp,
11
+ OAuthCollectionInitConfig,
12
+ OAuthDynamicCollection,
13
+ OAuthService,
14
+ } from '../OAuth/types';
15
+
16
+ export class OAuthCollection {
17
+ private readonly token: Token;
18
+ private readonly providers: Providers;
19
+ private readonly discoveryUrl: string;
20
+ private readonly accountId: string | undefined;
21
+ private readonly sdkUrl: string | undefined;
22
+ private readonly eventManagerUrl: string | undefined;
23
+ private readonly providersAccountId: string | undefined;
24
+ private readonly crossAccount: boolean;
25
+ private keyValueCollection: string;
26
+ private keyValueStorage: KeyValueStorage;
27
+ private serviceName: string;
28
+
29
+ constructor(params: OAuthCollectionConfig) {
30
+ const {
31
+ token,
32
+ discoveryUrl,
33
+ accountId,
34
+ serviceName,
35
+ keyValueCollection,
36
+ eventManagerUrl,
37
+ providersAccountId,
38
+ sdkUrl,
39
+ crossAccount = true,
40
+ } = params;
41
+
42
+ this.token = token;
43
+ this.sdkUrl = sdkUrl;
44
+ this.accountId = accountId;
45
+ this.crossAccount = crossAccount;
46
+ this.discoveryUrl = discoveryUrl;
47
+ this.serviceName = serviceName || '';
48
+ this.eventManagerUrl = eventManagerUrl;
49
+ this.providersAccountId = providersAccountId;
50
+ this.keyValueCollection = keyValueCollection || serviceName || '';
51
+
52
+ this.keyValueStorage = new KeyValueStorage({
53
+ token,
54
+ discoveryUrl,
55
+ accountId: crossAccount ? accountId : undefined,
56
+ sdkUrl,
57
+ });
58
+
59
+ this.providers = new Providers({
60
+ token,
61
+ discoveryUrl,
62
+ eventManagerUrl,
63
+ providersAccountId,
64
+ });
65
+ }
66
+
67
+
68
+ /**
69
+ * Allows to explicitly (re)initialize collection parameters
70
+ */
71
+ public init(params: OAuthCollectionInitConfig): void {
72
+ const { serviceName, keyValueCollection } = params;
73
+
74
+ this.serviceName = serviceName || this.serviceName;
75
+ this.keyValueCollection = keyValueCollection || this.keyValueCollection || this.serviceName;
76
+
77
+ if (!this.serviceName) {
78
+ throw new Error('No service name provided.');
79
+ }
80
+ }
81
+
82
+
83
+ /**
84
+ * Returns array of auth keys from this collection
85
+ */
86
+ public async listAuthorizations(dynamicCollection?: string): Promise<List<string>> {
87
+ const { items: records } = await this.keyValueStorage.listKeys(
88
+ this.keyValueCollection
89
+ );
90
+
91
+ const pattern = dynamicCollection ? `::oauth-collection::${dynamicCollection}` : '::oauth::';
92
+
93
+ return makeList<string>(records.map((record) => record.key)
94
+ .filter(key => key.includes(pattern)));
95
+ }
96
+
97
+ /**
98
+ * Returns array of OAuth applications for this service
99
+ */
100
+ public async listOAuthApps(): Promise<List<OAuthApp>> {
101
+ const appsStorageRecord = await this.keyValueStorage.getValueByKey(
102
+ this.keyValueCollection,
103
+ '__authorizer_apps'
104
+ );
105
+
106
+ if (!appsStorageRecord.value) {
107
+ return makeList<OAuthApp>([]);
108
+ }
109
+
110
+ const appsRecords = appsStorageRecord.value as Array<{
111
+ label: string;
112
+ value: Omit<OAuthApp, 'name'>;
113
+ }>;
114
+
115
+ return makeList<OAuthApp>(appsRecords.map((record) => ({
116
+ name: record.label,
117
+ ...record.value,
118
+ })));
119
+ }
120
+
121
+
122
+ /**
123
+ * Returns OAuth instance for given key
124
+ */
125
+ public async getAuthorization(key: string, dynamicCollection?: string): Promise<OAuth> {
126
+ if (!this.serviceName) throw new Error('No service name provided.');
127
+ let authName = undefined;
128
+
129
+ if (dynamicCollection) {
130
+ const { value } = await this.keyValueStorage.getValueByKey(
131
+ '__authorizer_dynamic_collections',
132
+ dynamicCollection
133
+ );
134
+
135
+ if (!value) {
136
+ throw new Error('Cynamic collection name is invalid');
137
+ }
138
+
139
+ const collection = value as OAuthDynamicCollection;
140
+ if (collection.service !== this.serviceName) {
141
+ throw new Error('Dynamic Collection and is related to other service than SDK Service Name');
142
+ }
143
+
144
+ authName = key;
145
+ key = collection.authorizations[key];
146
+
147
+ } else {
148
+ const { value } = await this.keyValueStorage.getValueByKey(
149
+ this.keyValueCollection,
150
+ encodeURIComponent(key)
151
+ );
152
+
153
+ if (!value) {
154
+ throw new Error('This authorization does not exist');
155
+ }
156
+ }
157
+
158
+ if (!key.includes('::oauth')) throw new Error('The OAuth authorization key should contain "oauth" type specifier.');
159
+
160
+ return new OAuth({
161
+ authName,
162
+ authKey: key,
163
+ dynamicCollection,
164
+ discoveryUrl: this.discoveryUrl,
165
+ eventManagerUrl: this.eventManagerUrl,
166
+ keyValueCollection: this.keyValueCollection,
167
+ providersAccountId: this.providersAccountId,
168
+ sdkUrl: this.sdkUrl,
169
+ serviceName: this.serviceName,
170
+ token: this.token,
171
+ });
172
+ }
173
+
174
+
175
+ /**
176
+ * Creates a new auth record in current collection with the given config.
177
+ * @returns Object with OAuth instance connected to created auth and authorizerUrl
178
+ * to redirect the user to for completing authorization
179
+ *
180
+ * ```typescript
181
+ * const {
182
+ * authorizeUrl, // redirect user to this url for completing authorization
183
+ * instance // new instance
184
+ * } = await oAuthCollectionInstance.createAuthorization({
185
+ * authName: 'my-auth-name',
186
+ * appId: 'my-app-id',
187
+ *
188
+ * // Optional params
189
+ * sdkUrl: 'sdkapi.staging.api.onereach.ai' // SDK API url. If passed, won't be fetched from discovery.
190
+ * eventManagerUrl: 'em.staging.api.onereach.ai' // Event Manager url. If passed, won't be fetched from discovery.
191
+ * providersAccountId: 'providers-account-id-v4' // Account ID of provider account. If passed, won't be fetched from discovery.
192
+ * keyValueCollection: 'custom_collection_name' // Pass this if you using custom name for key-value collection
193
+ * // that differs from serviceName.
194
+ * destinationAccount: 'CUSTOM' or 'PROVIDER' // Allows to save authorization data to custom account.
195
+ * customAccountId: 'custom-account-uuid-v4' // Account ID for destinationAccount == "CUSTOM".
196
+ * useNextProvider: boolean (default: false) // Use authorizer-next redirect endpoint.
197
+ * userScope: 'user:read' // Scopes for Slack service.
198
+ * useNonce: true // Allows to use Nonce to avoid repetition attacks.
199
+ * });
200
+ *
201
+ * // if you want to use returned instance, you must call a method
202
+ * that returns a promise that will be resolved when the user completes authorization process
203
+ * // if not, you can omit this step
204
+ * try {
205
+ * await instance.waitForCompletion()
206
+ * } catch (e) {
207
+ * // will be called if the user does not complete authorization within 5 minutes
208
+ * }
209
+ * ```
210
+ */
211
+ public async createAuthorization(
212
+ params: CreateOAuthInCollectionConfig,
213
+ ): Promise<CreateOAuthResult> {
214
+ if (!this.serviceName) throw new Error('No service name provided.');
215
+ return await OAuth.create({
216
+ ...params,
217
+ accountId: this.accountId,
218
+ crossAccount: this.crossAccount,
219
+ discoveryUrl: this.discoveryUrl,
220
+ eventManagerUrl: this.eventManagerUrl,
221
+ keyValueCollection: this.keyValueCollection,
222
+ providersAccountId: this.providersAccountId,
223
+ sdkUrl: this.sdkUrl,
224
+ serviceName: this.serviceName,
225
+ token: this.token,
226
+ });
227
+ }
228
+
229
+
230
+ /**
231
+ * Returns a list of predefined OAuth Services
232
+ */
233
+ public async listPredefinedServices(): Promise<Record<string, unknown>[]> {
234
+
235
+ const globalServices = await this.providers.makeRequest({
236
+ method: 'GET',
237
+ route: 'authorizer/services/list',
238
+ params: {
239
+ type: 'list',
240
+ },
241
+ }) as Record<string, unknown>;
242
+
243
+
244
+ const globalServicesList = Object.keys(globalServices).map(record => {
245
+ const label = record.split('__authorization_service_')[1]
246
+ .replace(/_/g, ' ');
247
+
248
+ const value = globalServices[record];
249
+
250
+ return {
251
+ label,
252
+ value,
253
+ };
254
+ }) as Record<string, unknown>[];
255
+
256
+
257
+ const localServices = await this.keyValueStorage.listKeys(
258
+ '__authorization_service_predefined_services_local',
259
+ undefined,
260
+ true
261
+ ) as unknown as Record<string, Record<string, string>[]>;
262
+
263
+
264
+ const localServicesList = localServices.items.map(el => {
265
+ const label = el.key
266
+ .split('__authorization_service_')[1]
267
+ .replace(/_/g, ' ') + ' (local)';
268
+
269
+ const value = el.value;
270
+ return {
271
+ label,
272
+ value,
273
+ };
274
+ });
275
+
276
+ return [...globalServicesList, ...localServicesList];
277
+ }
278
+
279
+
280
+ /**
281
+ * Defines a Local service
282
+ */
283
+ public async defineService(params: Omit<OAuthService, 'serviceName'>): Promise<void> {
284
+ if (!this.serviceName) throw new Error('No service name provided.');
285
+ const newService = {
286
+ ...params,
287
+ serviceName: this.serviceName,
288
+ } as OAuthService;
289
+
290
+ this.keyValueStorage.setValueByKey(
291
+ '__authorization_service_predefined_services_local',
292
+ this.serviceName,
293
+ newService
294
+ );
295
+ }
296
+
297
+
298
+ /**
299
+ * Creates a Dynamic OAuth collection
300
+ */
301
+ public async createDynamicCollection(dynamicCollectionName: string): Promise<void> {
302
+ if (!this.serviceName) throw new Error('No service name provided.');
303
+ if (!dynamicCollectionName) throw new Error('Dynamic collection name is empty or invalid');
304
+ const { value } = await this.keyValueStorage.getValueByKey(
305
+ '__authorizer_dynamic_collections',
306
+ dynamicCollectionName
307
+ );
308
+ const collection = value as OAuthDynamicCollection;
309
+
310
+ if (!value) {
311
+ await this.keyValueStorage.setValueByKey('__authorizer_dynamic_collections', dynamicCollectionName, {
312
+ name: dynamicCollectionName,
313
+ type: 'oauth',
314
+ service: this.keyValueCollection,
315
+ serviceConfigName: this.serviceName,
316
+ authorizations: {},
317
+ });
318
+ } else if (collection.type === 'oauth' && collection.service === this.serviceName) {
319
+ throw new Error('Same collection already exists');
320
+ } else {
321
+ throw new Error('Different collection exists with this name');
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Deletes a Dynamic OAuth collection
327
+ */
328
+ public async deleteDynamicCollection(dynamicCollectionName: string): Promise<void> {
329
+ if (!dynamicCollectionName) throw new Error('Dynamic collection name is empty or invalid');
330
+ const { value } = await this.keyValueStorage.getValueByKey(
331
+ '__authorizer_dynamic_collections',
332
+ dynamicCollectionName
333
+ );
334
+ const collection = value as OAuthDynamicCollection;
335
+
336
+ await Promise.all(
337
+ Object.keys(collection.authorizations)
338
+ .map(authName => {
339
+ return this.keyValueStorage.deleteKey(
340
+ collection.service,
341
+ encodeURIComponent(collection.authorizations[authName])
342
+ );
343
+ })
344
+ ).catch(() => {});
345
+
346
+ await this.keyValueStorage.deleteKey('__authorizer_dynamic_collections', dynamicCollectionName);
347
+ }
348
+ }
@@ -0,0 +1,3 @@
1
+ export { OAuthCollection } from './OAuthCollection';
2
+
3
+ export * from '../OAuth/types';
@@ -1,78 +1,305 @@
1
- import { Token } from '@or-sdk/base';
1
+ import { makeList, List } from '@or-sdk/base';
2
+ import { Providers } from '@or-sdk/providers';
2
3
  import { KeyValueStorage } from '@or-sdk/key-value-storage';
3
- import { TokenAuth } from './TokenAuth';
4
+ import { v4 as uuidv4 } from 'uuid';
5
+ import { createAuthKey, createDynamicKey } from './utils/createAuthKey';
4
6
 
5
7
  import {
6
8
  TokenCollectionConfig,
7
9
  CreateTokenAuthInCollectionConfig,
10
+ TokenAuthData,
11
+ TokenDynamicCollection,
8
12
  } from './types';
9
13
 
10
14
  export class TokenCollection {
11
- private readonly serviceName: string;
15
+ private serviceName: string;
12
16
  private readonly keyValueStorage: KeyValueStorage;
13
- private readonly localToken: Token;
14
- private readonly localDiscoveryUrl: string;
17
+ private readonly providers: Providers;
15
18
 
16
19
  constructor(params: TokenCollectionConfig) {
17
- const { token, discoveryUrl, serviceName } = params;
20
+ const { token, discoveryUrl, serviceName, accountId } = params;
18
21
 
19
- this.localToken = token;
20
- this.localDiscoveryUrl = discoveryUrl;
21
- this.serviceName = serviceName;
22
+ this.serviceName = serviceName || '';
22
23
  this.keyValueStorage = new KeyValueStorage({
23
24
  token,
24
25
  discoveryUrl,
26
+ accountId,
27
+ });
28
+
29
+ this.providers = new Providers({
30
+ token,
31
+ discoveryUrl,
25
32
  });
26
33
  }
27
34
 
35
+
36
+ /**
37
+ * Allows to explicitly (re-)set authorization service name
38
+ */
39
+ public init(serviceName: string) {
40
+ if (!serviceName) throw new Error('Servide name is required.');
41
+
42
+ this.serviceName = serviceName;
43
+ }
44
+
45
+
28
46
  /**
29
47
  * Returns array of auth keys from this collection
30
48
  */
31
- public async listAuthorizations(): Promise<string[]> {
32
- const { items: records } = await this.keyValueStorage.listKeys(this.serviceName);
49
+ public async listAuthorizations(dynamicCollectionName?: string): Promise<List<string>> {
50
+ const { items: records } = await this.keyValueStorage.listKeys(this.serviceName, '', false);
51
+
52
+ const pattern = dynamicCollectionName ? `::token-collection::${dynamicCollectionName}` : '::token::';
33
53
 
34
- return records.map((record) => record.key);
54
+ return makeList<string>(records.map((record) => record.key).filter(key => key.includes(pattern)));
35
55
  }
36
56
 
37
57
  /**
38
58
  * Returns TokenAuth instance for given key
39
59
  */
40
- public async getAuthorization(key: string): Promise<TokenAuth> {
41
- const record = await this.keyValueStorage.getValueByKey(this.serviceName, key);
60
+ public async getAuthorization(key: string, dynamicCollectionName: string): Promise<TokenAuthData> {
61
+ if (!this.serviceName) throw new Error('Service name is not defined.');
62
+
63
+ if (dynamicCollectionName) {
64
+ const { value } = await this.keyValueStorage.getValueByKey(
65
+ '__authorizer_dynamic_collections',
66
+ dynamicCollectionName
67
+ );
68
+ const collection = value as TokenDynamicCollection;
69
+ if (!collection) throw new Error('Dynamic collection name is invalid');
70
+
71
+ key = collection.authorizations[key];
72
+ }
73
+ if (!key.includes('::token')) throw new Error('The Token authorization key should contain "token" type specifier.');
74
+
75
+
76
+ const record = await this.keyValueStorage.getValueByKey(this.serviceName, encodeURIComponent(key));
42
77
  if (!record.value) {
43
78
  throw new Error('Authorization does not exist');
44
79
  }
45
80
 
46
- return new TokenAuth({
47
- serviceName: this.serviceName,
48
- authKey: key,
49
- discoveryUrl: this.localDiscoveryUrl,
50
- token: this.localToken,
51
- });
81
+ const authData = record.value as Omit<TokenAuthData, 'key'>;
82
+
83
+ if (!(authData.auth_name || authData._auth_name) || !(authData.date_created || authData._date_created)) {
84
+ throw new Error('Authorization is invalid.');
85
+ }
86
+
87
+ return {
88
+ ...authData,
89
+ key,
90
+ } as TokenAuthData;
52
91
  }
53
92
 
93
+
54
94
  /**
55
95
  * Creates a new auth record in current collection with the given config.
56
- * @returns TokenCollection instance connected to created auth
96
+ * @returns TokenAuthData object
57
97
  *
58
98
  * ```typescript
59
- * const tokenCollectionInstance = await tokenCollectionInstance.createAuthorization({
99
+ * const tokenAuthData = await tokenCollectionInstance.createAuthorization({
60
100
  * authName: 'my-auth-name',
61
101
  * credentials: {
62
102
  * token: 'secrettoken'
63
- * }
103
+ * },
104
+ * dynamicCollection: 'my-dynamic-collection' // Optional
64
105
  * });
65
106
  * ```
66
107
  */
67
108
  public async createAuthorization(
68
109
  params: CreateTokenAuthInCollectionConfig
69
- ): Promise<TokenAuth> {
70
- return await TokenAuth.create({
71
- discoveryUrl: this.localDiscoveryUrl,
72
- token: this.localToken,
73
- serviceName: this.serviceName,
74
- authName: params.authName,
75
- credentials: params.credentials,
76
- });
110
+ ): Promise<TokenAuthData> {
111
+ const { authName, credentials, dynamicCollection, destinationAccount = 'CURRENT', customAccountId } = params;
112
+
113
+ if (!this.serviceName) throw new Error('Service name is not defined.');
114
+ if (!authName || !credentials) throw new Error('Invalid authorization parameters passed.');
115
+
116
+ const id = uuidv4();
117
+ const authKey = dynamicCollection ? createDynamicKey(id, dynamicCollection) : createAuthKey(id, authName);
118
+
119
+ const authData = {
120
+ ...credentials,
121
+ auth_name: authName,
122
+ _date_created: new Date().toISOString(),
123
+ } as Omit<TokenAuthData, 'key'>;
124
+
125
+ if (dynamicCollection) {
126
+ const { value } = await this.keyValueStorage.getValueByKey('__authorizer_dynamic_collections', dynamicCollection);
127
+
128
+ const collection = (value || {
129
+ name: dynamicCollection,
130
+ type: 'token',
131
+ service: this.serviceName,
132
+ serviceConfigName: this.serviceName,
133
+ authorizations: {},
134
+ }) as TokenDynamicCollection;
135
+
136
+ if (collection.type !== 'token' || collection.service !== this.serviceName) {
137
+ throw new Error('Dynamic collection\'s type or service is invalid');
138
+ }
139
+
140
+ collection.authorizations[authName] = authKey;
141
+ await this.keyValueStorage.setValueByKey('__authorizer_dynamic_collections', dynamicCollection, collection);
142
+ }
143
+
144
+ // Accounts handling
145
+ if (destinationAccount === 'CURRENT') {
146
+ await this.keyValueStorage.setValueByKey(this.serviceName, encodeURIComponent(authKey), authData);
147
+ } else {
148
+ const localRecord = {
149
+ auth_name: authData.auth_name,
150
+ isRemote: true,
151
+ id,
152
+ };
153
+
154
+ if (destinationAccount === 'CUSTOM' && !customAccountId) {
155
+ throw new Error('Custom Account ID is required if destinationAccount === "CUSTOM"');
156
+ }
157
+
158
+ await this.providers.makeRequest({
159
+ route: 'authorizer/redirect',
160
+ params: {
161
+ method: 'PUT',
162
+ data: {
163
+ authData,
164
+ id,
165
+ storeAccount: destinationAccount,
166
+ storeCustomAccountId: destinationAccount === 'CUSTOM' ? customAccountId : undefined,
167
+ },
168
+ },
169
+ }).catch(() => { throw new Error('Could not save token to the specified account');});
170
+
171
+ await this.keyValueStorage.setValueByKey(this.serviceName, encodeURIComponent(authKey), localRecord);
172
+ }
173
+
174
+ return {
175
+ ...authData,
176
+ key: authKey,
177
+ } as TokenAuthData;
178
+ }
179
+
180
+
181
+ /**
182
+ * Updates credentials
183
+ */
184
+ public async updateAuthorization(
185
+ tokenAuth: TokenAuthData,
186
+ newCredentials: Record<string, unknown>
187
+ ): Promise<TokenAuthData> {
188
+ if (!this.serviceName) throw new Error('Service name is not defined.');
189
+ if (!newCredentials) throw new Error('New credentials are empty or invalid');
190
+ if (!tokenAuth || !tokenAuth.auth_name || !(tokenAuth.date_created || tokenAuth._date_created)) {
191
+ throw new Error('Token authorization data is invalid');
192
+ }
193
+
194
+ const updatedData = {
195
+ ...tokenAuth,
196
+ ...newCredentials,
197
+ auth_name: tokenAuth.auth_name,
198
+ _date_created: tokenAuth._date_created,
199
+ key: undefined,
200
+ };
201
+
202
+ const response = await this.keyValueStorage.setValueByKey(
203
+ this.serviceName,
204
+ encodeURIComponent(tokenAuth.key),
205
+ updatedData
206
+ );
207
+
208
+ const updatedRecord = response.value as Omit<TokenAuthData, 'key'>;
209
+ return {
210
+ ...updatedRecord,
211
+ key: tokenAuth.key,
212
+ } as TokenAuthData;
213
+ }
214
+
215
+
216
+ /**
217
+ * Deletes authorization from collection
218
+ */
219
+ public async deleteAuthorization(key: string): Promise<void> {
220
+ if (!this.serviceName) throw new Error('Service name is not defined.');
221
+ if (!key) throw new Error('Key is missing or invalid');
222
+
223
+ if (key.includes('::token-collection::')) {
224
+ const dynamicCollectionName = key.split('::')[2].split(' ')[0];
225
+ const { value } = await this.keyValueStorage.getValueByKey(
226
+ '__authorizer_dynamic_collections',
227
+ dynamicCollectionName
228
+ );
229
+
230
+ const collection = value as TokenDynamicCollection;
231
+ if (collection) {
232
+ const authName = Object.keys(collection.authorizations)
233
+ .find(name => collection.authorizations[name] === key);
234
+
235
+ if (authName) {
236
+ delete collection.authorizations[authName];
237
+ await this.keyValueStorage.setValueByKey(
238
+ '__authorizer_dynamic_collections',
239
+ dynamicCollectionName,
240
+ collection
241
+ );
242
+ }
243
+ }
244
+ }
245
+ await this.keyValueStorage.deleteKey(this.serviceName, encodeURIComponent(key));
246
+ }
247
+
248
+
249
+ /**
250
+ * Creates a Dynamic Token collection
251
+ */
252
+ public async createDynamicCollection(dynamicCollectionName: string): Promise<void> {
253
+ if (!dynamicCollectionName) throw new Error('Dynamic collection name is empty or invalid');
254
+ const { value } = await this.keyValueStorage.getValueByKey(
255
+ '__authorizer_dynamic_collections',
256
+ dynamicCollectionName
257
+ );
258
+ const collection = value as TokenDynamicCollection;
259
+
260
+ if (!value) {
261
+ await this.keyValueStorage.setValueByKey(
262
+ '__authorizer_dynamic_collections',
263
+ dynamicCollectionName,
264
+ {
265
+ name: dynamicCollectionName,
266
+ type: 'token',
267
+ service: this.serviceName,
268
+ serviceConfigName: this.serviceName,
269
+ authorizations: {},
270
+ });
271
+ } else if (collection.type === 'oauth' && collection.service === this.serviceName) {
272
+ throw new Error('Same collection already exists');
273
+ } else {
274
+ throw new Error('Different collection exists with this name');
275
+ }
276
+ }
277
+
278
+
279
+ /**
280
+ * Deletes a Dynamic collection
281
+ */
282
+ public async deleteDynamicCollection(dynamicCollectionName: string): Promise<void> {
283
+ if (!dynamicCollectionName) throw new Error('Dynamic collection name is empty or invalid');
284
+ const { value } = await this.keyValueStorage.getValueByKey(
285
+ '__authorizer_dynamic_collections',
286
+ dynamicCollectionName
287
+ );
288
+ const collection = value as TokenDynamicCollection;
289
+
290
+ await Promise.all(
291
+ Object.keys(collection.authorizations)
292
+ .map(authName => {
293
+ return this.keyValueStorage.deleteKey(
294
+ collection.service,
295
+ encodeURIComponent(collection.authorizations[authName])
296
+ );
297
+ })
298
+ ).catch(() => {});
299
+
300
+ await this.keyValueStorage.deleteKey(
301
+ '__authorizer_dynamic_collections',
302
+ dynamicCollectionName
303
+ );
77
304
  }
78
305
  }
@@ -0,0 +1,3 @@
1
+ export { TokenCollection } from './TokenCollection';
2
+
3
+ export * from './types';