@mindline/sync 1.0.28 → 1.0.30

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