@mindline/sync 1.0.29 → 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/configs.json +3 -14
- package/configs2.json +19 -31
- package/hybridspa.ts +822 -109
- package/index.d.ts +134 -25
- package/index.test.ts +1 -7
- package/index.ts +940 -134
- package/mockconfig.json +18 -0
- package/package.json +1 -2
- package/tasks.ts +103 -0
- package/{targets.json → tenants.json} +3 -1
- package/{targets2.json → tenants2.json} +6 -6
- package/workspaces.json +1 -1
- package/workspaces2.json +3 -3
package/hybridspa.ts
CHANGED
|
@@ -1,134 +1,847 @@
|
|
|
1
|
-
|
|
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 {
|
|
12
|
+
import { deserializeArray } from "class-transformer";
|
|
6
13
|
|
|
7
|
-
//
|
|
8
|
-
const graphConfig = {
|
|
9
|
-
|
|
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
|
-
|
|
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
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
+
}
|
|
108
492
|
}
|
|
109
|
-
|
|
110
|
-
console.log(
|
|
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;
|
|
111
500
|
}
|
|
112
501
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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 };
|
|
120
761
|
// make tenant endpoint call
|
|
121
762
|
try {
|
|
763
|
+
if (debug) debugger;
|
|
764
|
+
console.log(`Attempting PUT to ${tenantEndpoint}`);
|
|
122
765
|
let response = await fetch(tenantEndpoint, options);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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;
|
|
128
838
|
}
|
|
129
|
-
console.log("Fetched Data from Graph API:", data);
|
|
130
839
|
}
|
|
131
|
-
catch(error: any) {
|
|
132
|
-
|
|
840
|
+
catch (error: any) {
|
|
841
|
+
result.error = error.message;
|
|
842
|
+
result.status = 500;
|
|
843
|
+
result.result = false;
|
|
844
|
+
console.log(error.message);
|
|
133
845
|
}
|
|
846
|
+
return result;
|
|
134
847
|
}
|