@mindline/sync 1.0.36 → 1.0.38
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/.vs/VSWorkspaceState.json +1 -1
- package/.vs/slnx.sqlite +0 -0
- package/.vs/sync/FileContentIndex/33a3ee4b-9c43-4e0d-ae64-59dc9fd9c401.vsidx +0 -0
- package/.vs/sync/FileContentIndex/4199b40e-a51a-4aab-a20d-788df6fd8a20.vsidx +0 -0
- package/.vs/sync/FileContentIndex/48c8495d-1d23-4a29-98d1-5d8fb1fc34fd.vsidx +0 -0
- package/.vs/sync/v17/.wsuo +0 -0
- package/hybridspa.ts +42 -35
- package/index.d.ts +62 -5
- package/index.ts +592 -200
- package/package.json +4 -1
- package/syncmilestones.json +23 -0
- package/tsconfig.json +27 -0
- package/tsconfig.node.json +9 -0
- package/.vs/sync/FileContentIndex/65b0b1c9-0b62-4457-8808-4e1317638277.vsidx +0 -0
package/.vs/slnx.sqlite
CHANGED
|
Binary file
|
package/.vs/sync/v17/.wsuo
CHANGED
|
Binary file
|
package/hybridspa.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
User,
|
|
4
4
|
Tenant,
|
|
5
5
|
Config,
|
|
6
|
+
TenantConfigInfo,
|
|
6
7
|
APIResult
|
|
7
8
|
} from "./index";
|
|
8
9
|
import {
|
|
@@ -26,6 +27,7 @@ export const graphConfig = {
|
|
|
26
27
|
"https://dev-configurationapi-westus.azurewebsites.net/api/v1/configurations",
|
|
27
28
|
initEndpoint:
|
|
28
29
|
"https://dev-configurationapi-westus.azurewebsites.net/api/v1/configuration/init",
|
|
30
|
+
readerStartSyncEndpoint: "https://dev-configurationapi-westus.azurewebsites.net/api/v1/startSync",
|
|
29
31
|
tenantEndpoint:
|
|
30
32
|
"https://dev-configurationapi-westus.azurewebsites.net/api/v1/tenant",
|
|
31
33
|
tenantsEndpoint:
|
|
@@ -36,14 +38,17 @@ export const graphConfig = {
|
|
|
36
38
|
graphGroupsEndpoint: "https://graph.microsoft.com/v1.0/groups",
|
|
37
39
|
graphMailEndpoint: "https://graph.microsoft.com/v1.0/me/messages",
|
|
38
40
|
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
41
|
graphUsersEndpoint: "https://graph.microsoft.com/v1.0/users",
|
|
44
|
-
//
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
// sovereign cloud tenant info endpoints
|
|
43
|
+
graphTenantByDomainPredicate: "beta/tenantRelationships/findTenantInformationByDomainName",
|
|
44
|
+
graphTenantByIdPredicate: "beta/tenantRelationships/findTenantInformationByTenantId",
|
|
45
|
+
// authority values are based on the well-known OIDC auth endpoints
|
|
46
|
+
authorityWW: "https://login.microsoftonline.com/",
|
|
47
|
+
authorityWWRegex: /^(https:\/\/login\.microsoftonline\.(?:us|com)\/)([\dA-Fa-f]{8}-[\dA-Fa-f]{4}-[\dA-Fa-f]{4}-[\dA-Fa-f]{4}-[\dA-Fa-f]{12})\/oauth2\/authorize$/,
|
|
48
|
+
authorityUS: "https://login.microsoftonline.us/",
|
|
49
|
+
authorityUSRegex: /^(https:\/\/login\.microsoftonline\.(?:us|com)\/)([\dA-Fa-f]{8}-[\dA-Fa-f]{4}-[\dA-Fa-f]{4}-[\dA-Fa-f]{4}-[\dA-Fa-f]{12})\/oauth2\/authorize$/,
|
|
50
|
+
authorityCN: "https://login.partner.microsoftonline.cn/",
|
|
51
|
+
authorityCNRegex: /^(https:\/\/login\.partner\.microsoftonline\.cn\/)([\dA-Fa-f]{8}-[\dA-Fa-f]{4}-[\dA-Fa-f]{4}-[\dA-Fa-f]{4}-[\dA-Fa-f]{12})\/oauth2\/authorize$/,
|
|
47
52
|
};
|
|
48
53
|
// helper functions
|
|
49
54
|
async function defineHeaders(
|
|
@@ -128,7 +133,7 @@ export async function adminDelete(
|
|
|
128
133
|
console.log("Attempting DELETE from /admin: " + url!.href);
|
|
129
134
|
let response = await fetch(url!.href, options);
|
|
130
135
|
if (response.status === 200 && response.statusText === "OK") {
|
|
131
|
-
console.log(`Successful DELETE from
|
|
136
|
+
console.log(`Successful DELETE from /admin: ${url!.href}`);
|
|
132
137
|
return result;
|
|
133
138
|
} else {
|
|
134
139
|
result.error = await processErrors(response);
|
|
@@ -215,20 +220,9 @@ export async function adminPost(
|
|
|
215
220
|
workspaceId: string
|
|
216
221
|
): Promise<APIResult> {
|
|
217
222
|
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
|
-
) {
|
|
223
|
+
if (user.mail == "" || user.authority == "" || user.tid === "") {
|
|
230
224
|
result.result = false;
|
|
231
|
-
result.error = "
|
|
225
|
+
result.error = "adminPost: invalid argument";
|
|
232
226
|
result.status = 500;
|
|
233
227
|
return result;
|
|
234
228
|
}
|
|
@@ -340,13 +334,20 @@ export async function configPost(
|
|
|
340
334
|
"isEnabled": ${config.isEnabled},
|
|
341
335
|
"tenants": [`;
|
|
342
336
|
config.tenants.map((tci) => {
|
|
337
|
+
// be sure we send null and not "null" in body
|
|
338
|
+
let sourceGroupId: string = tci.sourceGroupId != "" ? `"${tci.sourceGroupId}"` : "null";
|
|
339
|
+
let sourceGroupName: string = tci.sourceGroupName != "" ? `"${tci.sourceGroupName}"` : "null";
|
|
340
|
+
let targetGroupId: string = tci.targetGroupId != "" ? `"${tci.targetGroupId}"` : "null";
|
|
341
|
+
let targetGroupName: string = tci.targetGroupName != "" ? `"${tci.targetGroupName}"` : "null";
|
|
343
342
|
// if last character is } we need a comma first
|
|
344
343
|
let needComma: boolean = configBody.slice(-1) === "}";
|
|
345
344
|
if (needComma) configBody += ",";
|
|
346
345
|
configBody += `{
|
|
347
346
|
"tenantId": "${tci.tid}",
|
|
348
|
-
"sourceGroupId":
|
|
349
|
-
"sourceGroupName":
|
|
347
|
+
"sourceGroupId": ${sourceGroupId},
|
|
348
|
+
"sourceGroupName": ${sourceGroupName},
|
|
349
|
+
"targetGroupId": ${targetGroupId},
|
|
350
|
+
"targetGroupName": ${targetGroupName},
|
|
350
351
|
"configurationTenantType": "${tci.configurationTenantType}"
|
|
351
352
|
}`;
|
|
352
353
|
});
|
|
@@ -409,15 +410,21 @@ export async function configPut(
|
|
|
409
410
|
"description": "${config.description}",
|
|
410
411
|
"isEnabled": ${config.isEnabled},
|
|
411
412
|
"tenants": [`;
|
|
412
|
-
config.tenants.map((tci) => {
|
|
413
|
+
config.tenants.map((tci: TenantConfigInfo) => {
|
|
413
414
|
// if last character is } we need a comma first
|
|
414
415
|
let needComma: boolean = configBody.slice(-1) === "}";
|
|
415
416
|
if (needComma) configBody += ",";
|
|
416
|
-
//
|
|
417
|
+
// be sure we send null and not "null" in body
|
|
418
|
+
let sourceGroupId: string = tci.sourceGroupId != "" ? `"${tci.sourceGroupId}"` : "null";
|
|
419
|
+
let sourceGroupName: string = tci.sourceGroupName != "" ? `"${tci.sourceGroupName}"` : "null";
|
|
420
|
+
let targetGroupId: string = tci.targetGroupId != "" ? `"${tci.targetGroupId}"` : "null";
|
|
421
|
+
let targetGroupName: string = tci.targetGroupName != "" ? `"${tci.targetGroupName}"` : "null";
|
|
417
422
|
configBody += `{
|
|
418
423
|
"tenantId": "${tci.tid}",
|
|
419
|
-
"sourceGroupId":
|
|
420
|
-
"sourceGroupName":
|
|
424
|
+
"sourceGroupId": ${sourceGroupId},
|
|
425
|
+
"sourceGroupName": ${sourceGroupName},
|
|
426
|
+
"targetGroupId": ${targetGroupId},
|
|
427
|
+
"targetGroupName": ${targetGroupName},
|
|
421
428
|
"configurationTenantType": "${tci.configurationTenantType}",
|
|
422
429
|
"deltaToken": "${tci.deltaToken}"
|
|
423
430
|
}`;
|
|
@@ -862,21 +869,21 @@ export async function readerPost(
|
|
|
862
869
|
result.status = 500;
|
|
863
870
|
return result;
|
|
864
871
|
}
|
|
865
|
-
// create reader endpoint
|
|
866
|
-
let readerEndpoint: string = graphConfig.readerStartSyncEndpoint
|
|
872
|
+
// create reader endpoint
|
|
873
|
+
let readerEndpoint: string = graphConfig.readerStartSyncEndpoint;
|
|
874
|
+
let url: URL = new URL(readerEndpoint);
|
|
875
|
+
url.searchParams.append("configurationId", config.id);
|
|
867
876
|
// create headers
|
|
868
877
|
const headers = await defineHeaders(instance, authorizedUser);
|
|
869
878
|
// make reader endpoint call
|
|
870
879
|
let options = { method: "POST", headers: headers };
|
|
871
880
|
try {
|
|
872
|
-
console.log("Attempting POST to /startSync: " +
|
|
873
|
-
let response = await fetch(
|
|
881
|
+
console.log("Attempting POST to /startSync: " + url.href);
|
|
882
|
+
let response = await fetch(url.href, options);
|
|
874
883
|
if (response.status === 200 && response.statusText === "OK") {
|
|
875
884
|
console.log(`Successful POST to /startSync: ${readerEndpoint}`);
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
textResponse = textResponse;
|
|
879
|
-
|
|
885
|
+
let jsonResponse = await response.json();
|
|
886
|
+
result.array = JSON.parse(jsonResponse.PayloadStr);
|
|
880
887
|
return result;
|
|
881
888
|
} else {
|
|
882
889
|
result.error = await processErrors(response);
|
package/index.d.ts
CHANGED
|
@@ -65,11 +65,14 @@ declare module "@mindline/sync" {
|
|
|
65
65
|
export class TenantConfigInfo {
|
|
66
66
|
tid: string; // tenant identifier
|
|
67
67
|
sourceGroupId: string; // source group - we can configure source group for reading
|
|
68
|
-
sourceGroupName: string; //
|
|
68
|
+
sourceGroupName: string; //
|
|
69
|
+
targetGroupId: string; // target group - we can configure target group for writing
|
|
70
|
+
targetGroupName: string; //
|
|
69
71
|
configurationTenantType: TenantConfigTypeStrings;
|
|
70
72
|
deltaToken: string;
|
|
71
|
-
|
|
73
|
+
usersWritten: number;
|
|
72
74
|
configId: string;
|
|
75
|
+
batchId: string;
|
|
73
76
|
}
|
|
74
77
|
export class Config {
|
|
75
78
|
id: string;
|
|
@@ -134,18 +137,70 @@ declare module "@mindline/sync" {
|
|
|
134
137
|
setEnd(endDate: Date): void;
|
|
135
138
|
setStart(startDate: Date): void;
|
|
136
139
|
}
|
|
140
|
+
export class Milestone {
|
|
141
|
+
Run: number;
|
|
142
|
+
Start: Date;
|
|
143
|
+
startDisplay: string;
|
|
144
|
+
POST: Date;
|
|
145
|
+
postDisplay: string;
|
|
146
|
+
Read: Date;
|
|
147
|
+
readDisplay: string;
|
|
148
|
+
Write: Date;
|
|
149
|
+
writeDisplay: string;
|
|
150
|
+
Duration: Date;
|
|
151
|
+
durationDisplay: string;
|
|
152
|
+
constructor(run: number);
|
|
153
|
+
start(start: string): void;
|
|
154
|
+
post(post: string): void;
|
|
155
|
+
read(read: string): void;
|
|
156
|
+
write(write: string): void;
|
|
157
|
+
}
|
|
158
|
+
export class MilestoneArray {
|
|
159
|
+
milestones: Milestone[];
|
|
160
|
+
constructor(bClearLocalStorage: boolean);
|
|
161
|
+
init(bClearLocalStorage: boolean): void;
|
|
162
|
+
save(): void;
|
|
163
|
+
start(setMilestones): void;
|
|
164
|
+
unstart(setMilestones): void;
|
|
165
|
+
post(setMilestones): void;
|
|
166
|
+
read(setMilestones): void;
|
|
167
|
+
write(setMilestones): void;
|
|
168
|
+
#initFromObjects(milestones: Milestones): void;
|
|
169
|
+
}
|
|
137
170
|
export class BatchArray {
|
|
138
171
|
tenantNodes: TenantNode[];
|
|
172
|
+
pb_startTS: number;
|
|
173
|
+
pb_progress: number;
|
|
174
|
+
pb_increment: number;
|
|
175
|
+
pb_idle: number;
|
|
176
|
+
pb_idleMax: number;
|
|
177
|
+
pb_timer;
|
|
178
|
+
milestoneArray: MilestoneArray;
|
|
139
179
|
constructor(config: Config|null, syncPortalGlobalState: InitInfo|null, bClearLocalStorage: boolean);
|
|
140
180
|
// populate tenantNodes based on config tenants
|
|
141
|
-
init(config: Config|null, syncPortalGlobalState: InitInfo|null, bClearLocalStorage: boolean): void;
|
|
142
|
-
|
|
181
|
+
init(config: Config|null|undefined, syncPortalGlobalState: InitInfo|null, bClearLocalStorage: boolean): void;
|
|
182
|
+
initializeProgressBar(setSyncProgress, setConfigSyncResult, setIdleText, setMilestones): void;
|
|
183
|
+
uninitializeProgressBar(setSyncProgress, setConfigSyncResult, setIdleText, setMilestones): void;
|
|
184
|
+
initializeSignalR(
|
|
185
|
+
config: Config | null | undefined,
|
|
186
|
+
syncPortalGlobalState: InitInfo | null,
|
|
187
|
+
batchIdArray: Array<Object>,
|
|
188
|
+
setRefreshDeltaTrigger,
|
|
189
|
+
setReadersTotal,
|
|
190
|
+
setReadersCurrent,
|
|
191
|
+
setWritersTotal,
|
|
192
|
+
setWritersCurrent,
|
|
193
|
+
setMilestones,
|
|
194
|
+
setConfigSyncResult,
|
|
195
|
+
bClearLocalStorage: boolean): void;
|
|
196
|
+
startSync(instance: IPublicClientApplication, authorizedUser: User | null | undefined, config: Config | null | undefined): APIResult;
|
|
143
197
|
}
|
|
144
198
|
export class TenantNode {
|
|
145
199
|
expanded: boolean;
|
|
146
200
|
status: string;
|
|
147
201
|
name: string;
|
|
148
202
|
tid: string;
|
|
203
|
+
batchId: string;
|
|
149
204
|
total: number;
|
|
150
205
|
read: number;
|
|
151
206
|
written: number;
|
|
@@ -158,6 +213,7 @@ declare module "@mindline/sync" {
|
|
|
158
213
|
result: boolean;
|
|
159
214
|
status: number;
|
|
160
215
|
error: string;
|
|
216
|
+
array: Array<Object> | null;
|
|
161
217
|
constructor();
|
|
162
218
|
}
|
|
163
219
|
//
|
|
@@ -170,7 +226,8 @@ declare module "@mindline/sync" {
|
|
|
170
226
|
export function signOut(user: User): void;
|
|
171
227
|
export function tenantRelationshipsGetByDomain(loggedInuser: User, tenant: Tenant, instance: IPublicClientApplication, debug: boolean): boolean;
|
|
172
228
|
export function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, tasks: TaskArray, debug: boolean): boolean;
|
|
173
|
-
export function
|
|
229
|
+
export function tenantUnauthenticatedLookup(tenant: Tenant, debug: boolean): Promise<boolean>;
|
|
230
|
+
export function usersGet(tenant: Tenant): { users: string[], error: string };
|
|
174
231
|
//
|
|
175
232
|
// Mindline Config API
|
|
176
233
|
//
|