@mindline/sync 1.0.29 → 1.0.31

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/hybridspa.ts CHANGED
@@ -1,134 +1,893 @@
1
- import {
2
- IPublicClientApplication,
3
- AuthenticationResult,
1
+ //hybridspa.ts - calls to Mindline Config API
2
+ import {
3
+ User,
4
+ Tenant,
5
+ Config,
6
+ APIResult
7
+ } from "./index";
8
+ import {
9
+ IPublicClientApplication,
10
+ AuthenticationResult,
4
11
  } from "@azure/msal-browser";
5
- import { User } from "@mindline/sync";
12
+ import { deserializeArray } from "class-transformer";
6
13
 
7
- // Add here the endpoints for MS Graph API services you would like to use.
8
- const graphConfig = {
9
- graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
10
- graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages",
11
- graphTenantEndpoint:
12
- "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId",
14
+ // add here endpoints for API services you would like to use.
15
+ export const graphConfig = {
16
+ // config API endpoints
17
+ adminEndpoint:
18
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/admin",
19
+ adminIncompleteEndpoint:
20
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/incomplete-admin",
21
+ adminsEndpoint:
22
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/admins",
23
+ configEndpoint:
24
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/configuration",
25
+ configsEndpoint:
26
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/configurations",
27
+ initEndpoint:
28
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/configuration/init",
29
+ tenantEndpoint:
30
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/tenant",
31
+ tenantsEndpoint:
32
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/tenants",
33
+ workspaceEndpoint:
34
+ "https://dev-configurationapi-westus.azurewebsites.net/api/v1/workspaces",
35
+ // graph API endpoints
36
+ graphGroupsEndpoint: "https://graph.microsoft.com/v1.0/groups",
37
+ graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages",
38
+ graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
39
+ graphTenantByDomainEndpoint:
40
+ "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByDomainName",
41
+ graphTenantByIdEndpoint:
42
+ "https://graph.microsoft.com/beta/tenantRelationships/findTenantInformationByTenantId",
43
+ graphUsersEndpoint: "https://graph.microsoft.com/v1.0/users",
44
+ // reader endpoint to trigger sync start
45
+ readerEndpoint: "https://dev-fn-reader-westus.azurewebsites.net/api/startSync/"
13
46
  };
14
-
15
- function updateUI(data, endpoint) {
16
- console.log("Graph API responded at: " + new Date().toString());
17
-
18
- if (endpoint === graphConfig.graphMeEndpoint) {
19
- console.log(data.jobTitle);
20
- console.log(data.mail);
21
- console.log(data.businessPhones[0]);
22
- console.log(data.officeLocation);
23
- } else if (endpoint === graphConfig.graphMailEndpoint) {
24
- if (data.value.length < 1) {
25
- alert("Your mailbox is empty!");
26
- } else {
27
- console.log("Displaying Emails for the signed in user.");
28
- data.value.map((d, i) => {
29
- // Keeping it simple
30
- if (i < 10) {
31
- console.log(data.officeLocation);
32
- console.log(d.subject);
33
- console.log(d.from.emailAddress.address);
34
- }
35
- });
36
- }
37
- }
47
+ // helper functions
48
+ async function defineHeaders(
49
+ instance: IPublicClientApplication,
50
+ user: User
51
+ ): Promise<Headers> {
52
+ const headers = new Headers();
53
+ headers.append("Content-Type", "application/json");
54
+ headers.append("accept", "*/*");
55
+ // authorization header - if needed, retrieve and cache access token
56
+ if (user.accessToken == null || user.accessToken === "") {
57
+ try {
58
+ let response: AuthenticationResult = await instance.acquireTokenByCode({
59
+ code: user.spacode,
60
+ });
61
+ user.accessToken = response.accessToken; // cache access token
62
+ console.log("Front end token acquired: " + user.accessToken.slice(0, 20));
63
+ }
64
+ catch (error: any) {
65
+ console.log("Front end token failure: " + error);
66
+ }
67
+ }
68
+ headers.append("Authorization", `Bearer ${user.accessToken}`);
69
+ return headers;
38
70
  }
39
-
40
- // Helper function to call MS Graph API endpoint
41
- // using authorization bearer token scheme
42
- function callMSGraph(endpoint, token, callback) {
43
- const headers = new Headers();
44
- const bearer = `Bearer ${token}`;
45
- headers.append("Authorization", bearer);
46
-
47
- const options = {
48
- method: "GET",
49
- headers: headers,
50
- };
51
-
52
- console.log("request made to Graph API at: " + new Date().toString());
53
-
54
- fetch(endpoint, options)
55
- .then((response) => response.json())
56
- .then((response) => callback(response, endpoint))
57
- .then((result) => {
58
- console.log("Successfully Fetched Data from Graph API:", result);
59
- })
60
- .catch((error) => console.log(error));
71
+ async function processErrors(response: Response): Promise<string> {
72
+ let errorString: string = "";
73
+ if (response.status === 401) {
74
+ errorString = response.statusText;
75
+ }
76
+ else {
77
+ let data = await response.json();
78
+ if (data.error !== undefined) {
79
+ errorString = `Error: ${data.error} Message: ${data.message}`;
80
+ } else if (data.errors !== undefined) {
81
+ let errorArray = Object.keys(data.errors);
82
+ let errorlist: string = "";
83
+ errorString = errorArray.reduce(
84
+ (acc, curr) => acc + curr + ": " + data.errors[curr] + " ",
85
+ errorlist
86
+ );
87
+ } else if (data.title !== undefined) {
88
+ errorString = data.title;
89
+ } else {
90
+ debugger;
91
+ }
92
+ }
93
+ return errorString;
61
94
  }
62
-
63
- ///get Token
64
- function getTokenByCode(spaCode: string, instance: IPublicClientApplication) {
65
- var code = spaCode;
66
- const scopes = ["user.read"];
67
-
68
- console.log("MSAL: acquireTokenByCode hybrid parameters present");
69
-
70
- var authResult = instance.acquireTokenByCode({
71
- code,
72
- scopes,
73
- });
74
- console.log(authResult);
75
-
76
- return authResult;
95
+ //adminDelete
96
+ export async function adminDelete(
97
+ instance: IPublicClientApplication,
98
+ authorizedUser: User,
99
+ user: User,
100
+ workspaceId: string
101
+ ): Promise<APIResult> {
102
+ let result: APIResult = new APIResult();
103
+ // we need either oid or mail for the user and valid workspace id
104
+ if ((user.oid == "" && user.mail == "") || workspaceId == "") {
105
+ result.result = false;
106
+ result.error = "adminDelete: invalid parameters";
107
+ result.status = 500;
108
+ return result;
109
+ }
110
+ // are we performing deletion of a full admin?
111
+ let url: URL | null = null;
112
+ if (user.oid !== user.mail) {
113
+ url = new URL(graphConfig.adminEndpoint);
114
+ url.searchParams.append("userId", user.oid);
115
+ url.searchParams.append("workspaceId", workspaceId);
116
+ }
117
+ // or of an incomplete admin?
118
+ else if (user.mail !== "") {
119
+ url = new URL(graphConfig.adminIncompleteEndpoint);
120
+ url.searchParams.append("email", user.mail);
121
+ url.searchParams.append("workspaceId", workspaceId);
122
+ }
123
+ // create headers
124
+ const headers = await defineHeaders(instance, authorizedUser);
125
+ // make endpoint call
126
+ let options = { method: "DELETE", headers: headers };
127
+ try {
128
+ console.log("Attempting DELETE from /admin: " + url!.href);
129
+ let response = await fetch(url!.href, options);
130
+ if (response.status === 200 && response.statusText === "OK") {
131
+ console.log(`Successful DELETE from //admin: ${url!.href}`);
132
+ return result;
133
+ } else {
134
+ result.error = await processErrors(response);
135
+ console.log(`Failed DELETE from /admin: ${url.href}`);
136
+ console.log(result.error);
137
+ result.status = 500;
138
+ result.result = false;
139
+ return result;
140
+ }
141
+ } catch (error: any) {
142
+ result.error = error.message;
143
+ result.status = 500;
144
+ result.result = false;
145
+ console.log(error.message);
146
+ }
147
+ return result;
77
148
  }
78
-
79
- //See Profile
80
- function seeProfile(spaCode: string, instance: IPublicClientApplication) {
81
- getTokenByCode(spaCode, instance)
82
- .then((response) => {
83
- callMSGraph(graphConfig.graphMeEndpoint, response.accessToken, updateUI);
84
- })
85
- .catch((error) => {
86
- console.log(error);
149
+ //adminsGet
150
+ export async function adminsGet(
151
+ instance: IPublicClientApplication,
152
+ authorizedUser: User,
153
+ workspaceID: string,
154
+ debug: boolean
155
+ ): Promise<APIResult> {
156
+ let result: APIResult = new APIResult();
157
+ // we need a workspace id
158
+ if (workspaceID === "") {
159
+ result.result = false;
160
+ result.status = 500;
161
+ result.error = "adminsGet: no workspace provided";
162
+ return result;
163
+ }
164
+ // create endpoint
165
+ let adminsEndpoint: string = graphConfig.adminsEndpoint;
166
+ // add parameter to endpoint
167
+ let url: URL = new URL(adminsEndpoint);
168
+ url.searchParams.append("workspaceId", workspaceID);
169
+ // create headers
170
+ const headers = await defineHeaders(instance, authorizedUser);
171
+ // make endpoint call
172
+ let options = { method: "GET", headers: headers };
173
+ try {
174
+ if (debug) debugger;
175
+ console.log("Attempting GET from /admins: " + url.href);
176
+ let response = await fetch(url.href, options);
177
+ if (response.status === 200 && response.statusText === "OK") {
178
+ let returnedArray: Array<Object> = await response.json();
179
+ if (returnedArray != null) {
180
+ result.array = returnedArray;
181
+ let initialValue: string = "";
182
+ console.log(`Successful GET from /admins: ${result.array.reduce((acc, curr) => acc + curr.email + " ", initialValue)}`);
183
+ return result;
184
+ }
185
+ else {
186
+ result.error = `Failed GET from /admins: failed to JSON-parse response`;
187
+ console.log(result.error);
188
+ result.status = 500;
189
+ result.result = false;
190
+ return result;
191
+ }
192
+ }
193
+ else {
194
+ console.log(`Failed GET from /admins: ${url.href}`);
195
+ result.error = await processErrors(response);
196
+ result.status = 500;
197
+ result.result = false;
198
+ console.log(result.error);
199
+ return result;
200
+ }
201
+ }
202
+ catch (error: any) {
203
+ result.error = error.message;
204
+ result.status = 500;
205
+ result.result = false;
206
+ console.log(error.message);
207
+ }
208
+ return result;
209
+ }
210
+ //adminPost: write validated admin to back end
211
+ export async function adminPost(
212
+ instance: IPublicClientApplication,
213
+ authorizedUser: User,
214
+ user: User,
215
+ workspaceId: string
216
+ ): Promise<APIResult> {
217
+ let result: APIResult = new APIResult();
218
+ if (
219
+ user.mail == null ||
220
+ user.mail === "" ||
221
+ user.authority == null ||
222
+ user.authority === "" ||
223
+ user.tid == null ||
224
+ user.tid === "" ||
225
+ user.companyName == null ||
226
+ user.companyName === "" ||
227
+ user.companyDomain == null ||
228
+ user.companyDomain === ""
229
+ ) {
230
+ result.result = false;
231
+ result.error = "configPost: invalid config ID";
232
+ result.status = 500;
233
+ return result;
234
+ }
235
+ // create admin endpoint
236
+ let adminEndpoint: string = graphConfig.adminEndpoint;
237
+ // create headers
238
+ const headers = await defineHeaders(instance, authorizedUser);
239
+ // create admin body
240
+ let adminBody: string = `
241
+ {"email": "${user.mail}",
242
+ "tenantId": "${user.tid}",
243
+ "workspaceId": "${workspaceId}"
244
+ }`;
245
+ let options = { method: "POST", headers: headers, body: adminBody };
246
+ // make admin endpoint call
247
+ try {
248
+ console.log("Attempting POST to /admin: " + adminEndpoint);
249
+ let response = await fetch(adminEndpoint, options);
250
+ if (response.status === 200 && response.statusText === "OK") {
251
+ console.log(`Successful POST to /admin: ${adminBody}`);
252
+ return result;
253
+ } else {
254
+ result.error = await processErrors(response);
255
+ console.log(`Failed POST to /admin: ${adminBody}`);
256
+ console.log(result.error);
257
+ result.status = 500;
258
+ result.result = false;
259
+ return result;
260
+ }
261
+ } catch (error: any) {
262
+ result.error = error.message;
263
+ result.status = 500;
264
+ result.result = false;
265
+ console.log(error.message);
266
+ }
267
+ return result;
268
+ }
269
+ //configDelete
270
+ export async function configDelete(
271
+ instance: IPublicClientApplication,
272
+ authorizedUser: User,
273
+ config: Config,
274
+ workspaceId: string,
275
+ debug: boolean
276
+ ): Promise<APIResult> {
277
+ let result: APIResult = new APIResult();
278
+ if (config.id === "" || workspaceId == "") {
279
+ result.result = false;
280
+ result.error = "configPost: invalid config ID";
281
+ result.status = 500;
282
+ return result;
283
+ }
284
+ let url: URL | null = null;
285
+ url = new URL(graphConfig.configEndpoint);
286
+ url.searchParams.append("configurationId", config.id);
287
+ // create headers
288
+ const headers = await defineHeaders(instance, authorizedUser);
289
+ // make endpoint call
290
+ let options = { method: "DELETE", headers: headers };
291
+ try {
292
+ console.log("Attempting DELETE from /config: " + url.href);
293
+ let response = await fetch(url.href, options);
294
+ if (response.status === 200 && response.statusText === "OK") {
295
+ console.log(`Successful DELETE from /config`);
296
+ return result;
297
+ }
298
+ else {
299
+ result.error = await processErrors(response);
300
+ console.log(`Failed DELETE from ${url.href}`);
301
+ console.log(result.error);
302
+ result.status = 500;
303
+ result.result = false;
304
+ return result;
305
+ }
306
+ }
307
+ catch (error: any) {
308
+ result.error = error.message;
309
+ result.status = 500;
310
+ result.result = false;
311
+ console.log(error.message);
312
+ }
313
+ return result;
314
+ }
315
+ //configPost
316
+ export async function configPost(
317
+ instance: IPublicClientApplication,
318
+ authorizedUser: User,
319
+ config: Config,
320
+ workspaceId: string,
321
+ debug: boolean
322
+ ): Promise<APIResult> {
323
+ let result: APIResult = new APIResult();
324
+ if (config.id === "") {
325
+ result.result = false;
326
+ result.error = "configPost: invalid config ID";
327
+ result.status = 500;
328
+ return result;
329
+ }
330
+ // create no parameter config endpoint
331
+ let configEndpoint: string = graphConfig.configEndpoint;
332
+ // create config headers
333
+ const headers = await defineHeaders(instance, authorizedUser);
334
+ // create config body
335
+ let configBody: string = `
336
+ {
337
+ "workspaceId": "${workspaceId}",
338
+ "name": "${config.name}",
339
+ "description": "${config.description}",
340
+ "isEnabled": ${config.isEnabled},
341
+ "tenants": [`;
342
+ config.tenants.map((tci) => {
343
+ // if last character is } we need a comma first
344
+ let needComma: boolean = configBody.slice(-1) === "}";
345
+ if (needComma) configBody += ",";
346
+ configBody += `{
347
+ "tenantId": "${tci.tid}",
348
+ "sourceGroupId": "${tci.sourceGroupId}",
349
+ "sourceGroupName": "${tci.sourceGroupName}",
350
+ "configurationTenantType": "${tci.configurationTenantType}"
351
+ }`;
87
352
  });
353
+ configBody += `]}`;
354
+ let options = { method: "POST", headers: headers, body: configBody };
355
+ // make config endpoint call
356
+ try {
357
+ if (debug) debugger;
358
+ console.log("Attempting POST to /config: " + configEndpoint);
359
+ let response = await fetch(configEndpoint, options);
360
+ if (response.status === 200 && response.statusText === "OK") {
361
+ let data = await response.json();
362
+ config.id = data;
363
+ console.log(
364
+ `Successful ConfigID: ${data} from POST to /config: ${configBody}`
365
+ );
366
+ return result;
367
+ }
368
+ else {
369
+ result.error = await processErrors(response);
370
+ console.log(`Failed PUT to /config: ${configBody}`);
371
+ console.log(result.error);
372
+ result.status = 500;
373
+ result.result = false;
374
+ return result;
375
+ }
376
+ }
377
+ catch (error: any) {
378
+ result.status = 500;
379
+ result.result = false;
380
+ result.error = error.message;
381
+ console.log(result.error);
382
+ return result;
383
+ }
88
384
  }
89
-
90
- //Get Tenant Info
91
- export async function getTenantInfo(user: User, instance: IPublicClientApplication) {
92
- // do we already have a valid company name?
93
- if (typeof user.companyName !== 'undefined' && user.companyName !== "") return;
94
-
95
- // create tenant info endpoint
96
- var tenantEndpoint = graphConfig.graphTenantEndpoint;
97
- tenantEndpoint += "(tenantId='";
98
- tenantEndpoint += user.tid;
99
- tenantEndpoint += "')";
100
- console.log("Time: " + new Date().toString());
101
- console.log("Tenant Info Endpoint: " + tenantEndpoint);
102
-
103
- // if needed, retrieve and cache access token
104
- if (typeof user.accessToken === 'undefined' || user.accessToken === "") {
385
+ //configPut
386
+ export async function configPut(
387
+ instance: IPublicClientApplication,
388
+ authorizedUser: User,
389
+ config: Config,
390
+ debug: boolean
391
+ ): Promise<APIResult> {
392
+ let result: APIResult = new APIResult();
393
+ if (config.id === "") {
394
+ result.result = false;
395
+ result.error = "configPost: invalid config ID";
396
+ result.status = 500;
397
+ return result;
398
+ }
399
+ // create parametrized config endpoint
400
+ let configEndpoint: string = graphConfig.configEndpoint;
401
+ let url: URL = new URL(configEndpoint);
402
+ url.searchParams.append("configurationId", config.id);
403
+ // create config headers
404
+ const headers = await defineHeaders(instance, authorizedUser);
405
+ // create config body
406
+ let configBody: string = `
407
+ {
408
+ "name": "${config.name}",
409
+ "description": "${config.description}",
410
+ "isEnabled": ${config.isEnabled},
411
+ "tenants": [`;
412
+ config.tenants.map((tci) => {
413
+ // if last character is } we need a comma first
414
+ let needComma: boolean = configBody.slice(-1) === "}";
415
+ if (needComma) configBody += ",";
416
+ // decide whethere to send source group values
417
+ configBody += `{
418
+ "tenantId": "${tci.tid}",
419
+ "sourceGroupId": "${tci.sourceGroupId}",
420
+ "sourceGroupName": "${tci.sourceGroupName}",
421
+ "configurationTenantType": "${tci.configurationTenantType}"
422
+ }`;
423
+ });
424
+ configBody += `]}`;
425
+ let options = { method: "PUT", headers: headers, body: configBody };
426
+ // make config endpoint call
105
427
  try {
106
- let response = await instance.acquireTokenByCode({ code: user.spacode });
107
- user.accessToken = response.accessToken;
108
- }
109
- catch(error: any) {
110
- console.log(error);
111
- }
112
- }
113
-
114
- // prepare Authorization headers as part of options
115
- const headers = new Headers();
116
- const bearer = `Bearer ${user.accessToken}`;
117
- headers.append("Authorization", bearer);
118
- const options = { method: "GET", headers: headers };
119
-
120
- // make tenant endpoint call
121
- try {
122
- let response = await fetch(tenantEndpoint, options);
123
- let data = await response.json();
124
- if(data && data.displayName && data.displayName !== undefined)
428
+ if (debug) debugger;
429
+ console.log("Attempting PUT to /config: " + url.href);
430
+ let response = await fetch(url.href, options);
431
+ if (response.status === 200 && response.statusText === "OK") {
432
+ console.log(`Successful PUT to ${url.href}: ${configBody}`);
433
+ return result;
434
+ }
435
+ else {
436
+ result.error = await processErrors(response);
437
+ console.log(`Failed PUT to ${url.href}: ${configBody}`);
438
+ console.log(result.error);
439
+ result.status = 500;
440
+ result.result = false;
441
+ return result;
442
+ }
443
+ }
444
+ catch (error: any) {
445
+ result.error = error.message;
446
+ result.status = 500;
447
+ result.result = false;
448
+ console.log(error.message);
449
+ }
450
+ return result;
451
+ }
452
+ //configsGet
453
+ export async function configsGet(
454
+ instance: IPublicClientApplication,
455
+ authorizedUser: User,
456
+ workspaceID: string,
457
+ debug: boolean
458
+ ): Promise<APIResult> {
459
+ let result: APIResult = new APIResult();
460
+ // we need a workspace id
461
+ if (workspaceID === "") {
462
+ result.result = false;
463
+ result.status = 500;
464
+ result.error = "configsGet: no workspace provided";
465
+ return result;
466
+ }
467
+ // create endpoint
468
+ let configsEndpoint: string = graphConfig.configsEndpoint;
469
+ // add parameter to endpoint
470
+ let url: URL = new URL(configsEndpoint);
471
+ url.searchParams.append("workspaceId", workspaceID);
472
+ // create headers
473
+ const headers = await defineHeaders(instance, authorizedUser);
474
+ // make endpoint call
475
+ let options = { method: "GET", headers: headers };
476
+ try {
477
+ if (debug) debugger;
478
+ console.log("Attempting GET from /configurations: " + url.href);
479
+ let response = await fetch(url.href, options);
480
+ if (response.status === 200 && response.statusText === "OK") {
481
+ let returnedArray: Array<Object> = await response.json();
482
+ if (returnedArray != null) {
483
+ result.array = returnedArray;
484
+ let initialValue: string = "";
485
+ console.log(`Successful GET from /configurations: ${result.array.reduce((acc, curr) => acc + curr.name + " ", initialValue)}`);
486
+ return result;
487
+ }
488
+ else {
489
+ result.error = `Failed GET from /configurations: failed to JSON-parse response`;
490
+ console.log(result.error);
491
+ result.status = 500;
492
+ result.result = false;
493
+ return result;
494
+ }
495
+ }
496
+ else {
497
+ console.log(`Failed GET from /configurations: ${url.href}`);
498
+ result.error = await processErrors(response);
499
+ result.status = 500;
500
+ result.result = false;
501
+ console.log(result.error);
502
+ return result;
503
+ }
504
+ }
505
+ catch (error: any) {
506
+ result.error = error.message;
507
+ result.status = 500;
508
+ result.result = false;
509
+ console.log(error.message);
510
+ }
511
+ return result;
512
+ }
513
+ //initPost
514
+ export async function initPost(
515
+ instance: IPublicClientApplication,
516
+ authorizedUser: User,
517
+ user: User,
518
+ debug: boolean
519
+ ): Promise<APIResult> {
520
+ let result: APIResult = new APIResult();
521
+ // we expect valid company name and domain by this point
522
+ if (user.companyName === "" || user.companyDomain === "") {
523
+ result.result = false;
524
+ result.error = "initPost: invalid company name or domain"
525
+ result.status = 500;
526
+ return result;
527
+ }
528
+ // create init endpoint
529
+ let initEndpoint: string = graphConfig.initEndpoint;
530
+ // create init headers
531
+ const headers = await defineHeaders(instance, authorizedUser);
532
+ // create init body
533
+ let initBody: string = `
534
+ {
535
+ "tenantCreateModel": {
536
+ "tenantId": "${user.tid}",
537
+ "name": "${user.companyName}",
538
+ "domain": "${user.companyDomain}",
539
+ "type": "aad",
540
+ "authority": "${user.authority}"
541
+ }
542
+ }`;
543
+ let options = { method: "POST", headers: headers, body: initBody };
544
+ // make init endpoint call
545
+ try {
546
+ if (debug) debugger;
547
+ console.log("Attempting POST to /configuration/init: " + initEndpoint);
548
+ let response = await fetch(initEndpoint, options);
549
+ if (response.status === 200 && response.statusText === "OK") {
550
+ console.log(`Successful POST to /configuration/init: ${initBody}`);
551
+ return result;
552
+ }
553
+ else {
554
+ result.error = await processErrors(response);
555
+ result.status = 500;
556
+ result.result = false;
557
+ console.log(`Failed POST to /configuration/init: ${initBody}`);
558
+ console.log(result.error);
559
+ return result;
560
+ }
561
+ }
562
+ catch (error: any) {
563
+ result.error = error.message;
564
+ console.log(result.error);
565
+ }
566
+ result.status = 500;
567
+ result.result = false;
568
+ return result;
569
+ }
570
+ //tenantDelete
571
+ export async function tenantDelete(
572
+ instance: IPublicClientApplication,
573
+ authorizedUser: User,
574
+ tenant: Tenant,
575
+ workspaceId: string,
576
+ debug: boolean
577
+ ): Promise<APIResult> {
578
+ let result: APIResult = new APIResult();
579
+ // we expect valid tid amd workspaceId
580
+ if (tenant.tid === "" || workspaceId === "") {
581
+ result.result = false;
582
+ result.error = "tenantDelete: invalid tid, workspaceId";
583
+ result.status = 500;
584
+ return result;
585
+ }
586
+ // create parametrized tenant endpoint
587
+ let url: URL = new URL(graphConfig.tenantEndpoint);
588
+ url.searchParams.append("tenantId", tenant.tid);
589
+ url.searchParams.append("workspaceId", workspaceId);
590
+ // create headers
591
+ const headers = await defineHeaders(instance, authorizedUser);
592
+ // make tenant endpoint call
593
+ let options = { method: "DELETE", headers: headers };
594
+ try {
595
+ console.log("Attempting DELETE from /tenant: " + url.href);
596
+ let response = await fetch(url.href, options);
597
+ if (response.status === 200 && response.statusText === "OK") {
598
+ console.log(`Successful DELETE from /tenant: ${url.href}`);
599
+ return result;
600
+ }
601
+ else {
602
+ console.log(`Failed DELETE from /tenant: ${url.href}`);
603
+ result.error = await processErrors(response);
604
+ console.log(result.error);
605
+ result.status = 500;
606
+ result.result = false;
607
+ return result;
608
+ }
609
+ }
610
+ catch (error: any) {
611
+ result.error = error.message;
612
+ result.status = 500;
613
+ result.result = false;
614
+ console.log(result.error);
615
+ }
616
+ return result;
617
+ }
618
+ //tenantsGet
619
+ export async function tenantsGet(
620
+ instance: IPublicClientApplication,
621
+ authorizedUser: User,
622
+ workspaceID: string,
623
+ debug: boolean
624
+ ): Promise<APIResult> {
625
+ let result: APIResult = new APIResult();
626
+ // we need a workspace id
627
+ if (workspaceID === "") {
628
+ result.result = false;
629
+ result.status = 500;
630
+ result.error = "tenantsGet: no workspace provided";
631
+ return result;
632
+ }
633
+ // create endpoint
634
+ let tenantsEndpoint: string = graphConfig.tenantsEndpoint;
635
+ // add parameter to endpoint
636
+ let url: URL = new URL(tenantsEndpoint);
637
+ url.searchParams.append("workspaceId", workspaceID);
638
+ // create headers
639
+ const headers = await defineHeaders(instance, authorizedUser);
640
+ // make endpoint call
641
+ let options = { method: "GET", headers: headers };
642
+ try {
643
+ if (debug) debugger;
644
+ console.log(`Attempting GET from /tenants: ${url.href}`);
645
+ let response = await fetch(url.href, options);
646
+ if (response.status === 200 && response.statusText === "OK") {
647
+ let returnedArray: Array<Object> = await response.json();
648
+ if (returnedArray != null) {
649
+ result.array = returnedArray;
650
+ let initialValue: string = "";
651
+ console.log(`Successful GET from /tenants: ${result.array.reduce((acc, curr) => acc + curr.domain + " ", initialValue)}`);
652
+ return result;
653
+ }
654
+ else {
655
+ result.error = `Failed GET from /tenants: failed to JSON-parse response`;
656
+ console.log(result.error);
657
+ result.status = 500;
658
+ result.result = false;
659
+ return result;
660
+ }
661
+ }
662
+ else {
663
+ console.log(`Failed GET from /tenants: ${url.href}`);
664
+ result.error = await processErrors(response);
665
+ result.status = 500;
666
+ result.result = false;
667
+ console.log(result.error);
668
+ return result;
669
+ }
670
+ }
671
+ catch (error: any) {
672
+ result.error = error.message;
673
+ result.status = 500;
674
+ result.result = false;
675
+ console.log(error.message);
676
+ }
677
+ return result;
678
+ }
679
+ //tenantPost: write validated tenant to back end
680
+ export async function tenantPost(
681
+ instance: IPublicClientApplication,
682
+ addingUser: User,
683
+ tenant: Tenant,
684
+ workspaceId: string
685
+ ): Promise<APIResult> {
686
+ let result: APIResult = new APIResult();
687
+ // we expect valid tid, name, validated domain
688
+ if (tenant.tid === "" || tenant.name === "" || tenant.domain === "") {
689
+ result.result = false;
690
+ result.error = "tenantPost: invalid tid, name, domain";
691
+ result.status = 500;
692
+ return result;
693
+ }
694
+ // create parametrized tenant endpoint
695
+ let tenantEndpoint: string = graphConfig.tenantEndpoint;
696
+ let url: URL = new URL(tenantEndpoint);
697
+ url.searchParams.append("workspaceId", workspaceId);
698
+ // create tenant headers
699
+ const headers = await defineHeaders(instance, addingUser);
700
+ // create tenant body
701
+ let tenantBody: string = `
702
+ {"tenantId": "${tenant.tid}",
703
+ "name": "${tenant.name}",
704
+ "domain": "${tenant.domain}",
705
+ "type": 1,
706
+ "authority": "${tenant.authority}"
707
+ }`;
708
+ let options = { method: "POST", headers: headers, body: tenantBody };
709
+ // make tenant endpoint call
710
+ try {
711
+ console.log(`Attempting POST to ${url.href}: ${tenantBody}`);
712
+ let response = await fetch(url.href, options);
713
+ if (response.status === 200 && response.statusText === "OK") {
714
+ console.log(`Successful POST to ${url.href}: ${tenantBody}`);
715
+ return result;
716
+ }
717
+ else {
718
+ console.log(`Failed POST to ${url.href}: ${tenantBody}`);
719
+ result.error = await processErrors(response);
720
+ console.log(result.error);
721
+ result.status = 500;
722
+ result.result = false;
723
+ return result;
724
+ }
725
+ }
726
+ catch (error: any) {
727
+ result.error = error.message;
728
+ result.status = 500;
729
+ result.result = false;
730
+ console.log(result.error);
731
+ }
732
+ return result;
733
+ }
734
+ //tenantPut: write access token for onboarded tenant
735
+ export async function tenantPut(
736
+ instance: IPublicClientApplication,
737
+ authorizedUser: User,
738
+ tenant: Tenant,
739
+ debug: boolean
740
+ ): Promise<APIResult> {
741
+ let result: APIResult = new APIResult();
742
+ // we expect valid tid
743
+ if (tenant.tid === "") {
744
+ result.result = false;
745
+ result.error = "tenantPut: invalid tid";
746
+ result.status = 500;
747
+ return result;
748
+ }
749
+ // create tenant endpoint
750
+ let tenantEndpoint: string = graphConfig.tenantEndpoint;
751
+ // create tenant headers
752
+ const headers = await defineHeaders(instance, authorizedUser);
753
+ // be sure we send null and not "null" in body
754
+ let readAccessToken: string = tenant.readServicePrincipal
755
+ ? `"${tenant.readServicePrincipal}"`
756
+ : "null";
757
+ let writeAccessToken: string = tenant.writeServicePrincipal
758
+ ? `"${tenant.writeServicePrincipal}"`
759
+ : "null";
760
+ // create tenant body
761
+ let tenantBody: string = `
762
+ {"tenantId": "${tenant.tid}", "readServicePrincipal": ${readAccessToken}, "writeServicePrincipal": ${writeAccessToken}}`;
763
+ let options = { method: "PUT", headers: headers, body: tenantBody };
764
+ // make tenant endpoint call
765
+ try {
766
+ if (debug) debugger;
767
+ console.log(`Attempting PUT to ${tenantEndpoint}`);
768
+ let response = await fetch(tenantEndpoint, options);
769
+ if (response.status === 200 && response.statusText === "OK") {
770
+ console.log(`Successful PUT to ${tenantEndpoint}`);
771
+ return result;
772
+ }
773
+ else {
774
+ console.log(`Failed PUT to ${tenantEndpoint}: ${tenantBody}`);
775
+ result.error = await processErrors(response);
776
+ console.log(result.error);
777
+ result.status = 500;
778
+ result.result = false;
779
+ return result;
780
+ }
781
+ }
782
+ catch (error: any) {
783
+ result.error = error.message;
784
+ result.status = 500;
785
+ result.result = false;
786
+ console.log(result.error);
787
+ }
788
+ return result;
789
+ }
790
+ //workspacesGet
791
+ export async function workspacesGet(
792
+ instance: IPublicClientApplication,
793
+ authorizedUser: User,
794
+ user: User,
795
+ debug: boolean
796
+ ): Promise<APIResult> {
797
+ let result: APIResult = new APIResult();
798
+ // we need a valid email address
799
+ if (user.mail == undefined || user.mail == "") {
800
+ result.result = false;
801
+ result.status = 500;
802
+ result.error = "adminsGet: no workspace provided";
803
+ return result;
804
+ }
805
+ // create workspaces endpoint
806
+ let workspaceEndpoint: string = graphConfig.workspaceEndpoint;
807
+ // add email parameter to endpoint
808
+ let url: URL = new URL(workspaceEndpoint);
809
+ url.searchParams.append("userEmail", user.mail);
810
+ // create workspace headers
811
+ const headers = await defineHeaders(instance, authorizedUser);
812
+ // make workspace endpoint call
813
+ let options = { method: "GET", headers: headers };
814
+ try {
815
+ if (debug) debugger;
816
+ console.log("Attempting GET from /workspaces endpoint: " + url.href);
817
+ let response = await fetch(url.href, options);
818
+ if (response.status === 200 && response.statusText === "OK") {
819
+ let returnedArray: Array<Object> = await response.json();
820
+ if (returnedArray != null) {
821
+ result.array = returnedArray;
822
+ let initialValue: string = "";
823
+ console.log(`Successful GET from /workspaces: ${result.array.reduce((acc, curr) => acc + curr.name + " ", initialValue)}`);
824
+ return result;
825
+ }
826
+ else {
827
+ result.error = `Failed GET from /workspaces: failed to JSON-parse response`;
828
+ console.log(result.error);
829
+ result.status = 500;
830
+ result.result = false;
831
+ return result;
832
+ }
833
+ }
834
+ else {
835
+ console.log(`Failed GET from /workspaces: ${url.href}`);
836
+ result.error = await processErrors(response);
837
+ result.status = 500;
838
+ result.result = false;
839
+ console.log(result.error);
840
+ return result;
841
+ }
842
+ }
843
+ catch (error: any) {
844
+ result.error = error.message;
845
+ result.status = 500;
846
+ result.result = false;
847
+ console.log(error.message);
848
+ }
849
+ return result;
850
+ }
851
+ //readerPost
852
+ export async function readerPost(
853
+ instance: IPublicClientApplication,
854
+ authorizedUser: User,
855
+ config: Config
856
+ ): Promise<APIResult> {
857
+ let result: APIResult = new APIResult();
858
+ if (instance == null || authorizedUser == null)
125
859
  {
126
- user.companyName = data.displayName;
127
- user.companyDomain = data.defaultDomainName;
128
- }
129
- console.log("Fetched Data from Graph API:", data);
130
- }
131
- catch(error: any) {
132
- console.log(error);
133
- }
134
- }
860
+ result.result = false;
861
+ result.error = "readerPost: invalid parameters";
862
+ result.status = 500;
863
+ return result;
864
+ }
865
+ // create reader endpoint with config ID
866
+ let readerEndpoint: string = graphConfig.readerEndpoint + config.id;
867
+ // create headers
868
+ const headers = await defineHeaders(instance, authorizedUser);
869
+ // make reader endpoint call
870
+ let options = { method: "POST", headers: headers };
871
+ try {
872
+ console.log("Attempting POST to /startSync: " + readerEndpoint);
873
+ debugger;
874
+ let response = await fetch(readerEndpoint, options);
875
+ if (response.status === 200 && response.statusText === "OK") {
876
+ console.log(`Successful POST to /startSync: ${readerEndpoint}`);
877
+ return result;
878
+ } else {
879
+ result.error = await processErrors(response);
880
+ console.log(`Failed POST to /startSync: ${readerEndpoint}`);
881
+ console.log(result.error);
882
+ result.status = 500;
883
+ result.result = false;
884
+ return result;
885
+ }
886
+ } catch (error: any) {
887
+ result.error = error.message;
888
+ result.status = 500;
889
+ result.result = false;
890
+ console.log(error.message);
891
+ }
892
+ return result;
893
+ }