@mindline/sync 1.0.46 → 1.0.49
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/cdd6fa40-5a79-4b31-94d6-8cd1182752af.vsidx +0 -0
- package/.vs/sync/v17/.wsuo +0 -0
- package/hybridspa.ts +8 -1
- package/index.d.ts +1 -1
- package/index.ts +36 -6
- package/package.json +1 -1
- package/tasks.ts +2 -10
- package/.vs/sync/FileContentIndex/bd306da7-ee26-4cdb-9a88-48087df60928.vsidx +0 -0
package/.vs/slnx.sqlite
CHANGED
|
Binary file
|
package/.vs/sync/v17/.wsuo
CHANGED
|
Binary file
|
package/hybridspa.ts
CHANGED
|
@@ -893,7 +893,14 @@ export async function readerPost(
|
|
|
893
893
|
if (response.status === 200 && response.statusText === "OK") {
|
|
894
894
|
console.log(`Successful POST to /startSync: ${readerEndpoint}`);
|
|
895
895
|
let jsonResponse = await response.json();
|
|
896
|
-
|
|
896
|
+
if (jsonResponse.PayloadStr != "") {
|
|
897
|
+
result.array = JSON.parse(jsonResponse.PayloadStr);
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
result.result = false;
|
|
901
|
+
result.error = "readerPost: blank payload returned, sync may be disabled on back end";
|
|
902
|
+
result.status = 500;
|
|
903
|
+
}
|
|
897
904
|
return result;
|
|
898
905
|
} else {
|
|
899
906
|
result.error = await processErrors(response);
|
package/index.d.ts
CHANGED
|
@@ -116,7 +116,6 @@ declare module "@mindline/sync" {
|
|
|
116
116
|
export type TaskType = "initialization" |
|
|
117
117
|
"authenticate user" |
|
|
118
118
|
"reload React" |
|
|
119
|
-
"PUT tenant" |
|
|
120
119
|
"GET tenant details" |
|
|
121
120
|
"POST config init" |
|
|
122
121
|
"GET workspaces" |
|
|
@@ -233,6 +232,7 @@ declare module "@mindline/sync" {
|
|
|
233
232
|
export function groupsGet(instance: IPublicClientApplication, user: User | undefined, groupSearchString: string): Promise<{groups: Group[], error: string}>;
|
|
234
233
|
export function signIn(user: User, tasks: TaskArray): void;
|
|
235
234
|
export function signInIncrementally(user: User, scope: string): void;
|
|
235
|
+
export function requestAdminConsent(user: User, scope: string): void;
|
|
236
236
|
export function signOut(user: User): boolean;
|
|
237
237
|
export function tenantRelationshipsGetByDomain(loggedInuser: User, tenant: Tenant, instance: IPublicClientApplication, debug: boolean): boolean;
|
|
238
238
|
export function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, tasks: TaskArray, debug: boolean): boolean;
|
package/index.ts
CHANGED
|
@@ -391,7 +391,6 @@ export class InitInfo {
|
|
|
391
391
|
export type TaskType = "initialization" |
|
|
392
392
|
"authenticate user" |
|
|
393
393
|
"reload React" |
|
|
394
|
-
"PUT tenant" |
|
|
395
394
|
"GET tenant details" |
|
|
396
395
|
"POST config init" |
|
|
397
396
|
"GET workspaces" |
|
|
@@ -822,7 +821,7 @@ export class BatchArray {
|
|
|
822
821
|
this.pb_increment = 1;
|
|
823
822
|
this.pb_idle = 0;
|
|
824
823
|
this.pb_idleMax = 0;
|
|
825
|
-
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}]`);
|
|
824
|
+
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}/60]`);
|
|
826
825
|
this.pb_timer = setInterval(() => {
|
|
827
826
|
// if signalR has finished the sync, stop the timer
|
|
828
827
|
if (this.milestoneArray.milestones[0].Write != null) {
|
|
@@ -833,10 +832,10 @@ export class BatchArray {
|
|
|
833
832
|
setIdleText(`Complete. [max idle: ${this.pb_idleMax}]`);
|
|
834
833
|
}
|
|
835
834
|
else {
|
|
836
|
-
// if we've gone
|
|
835
|
+
// if we've gone 60 seconds without a signalR message, finish the sync
|
|
837
836
|
this.pb_idle = this.pb_idle + 1;
|
|
838
837
|
this.pb_idleMax = Math.max(this.pb_idle, this.pb_idleMax);
|
|
839
|
-
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}]`);
|
|
838
|
+
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}/60]`);
|
|
840
839
|
if (this.pb_idle >= 60) {
|
|
841
840
|
clearInterval(this.pb_timer);
|
|
842
841
|
this.pb_timer = null;
|
|
@@ -916,11 +915,13 @@ export class BatchArray {
|
|
|
916
915
|
let bTotalCount = statskeys[j].endsWith("TotalCount");
|
|
917
916
|
let bCurrentCount = statskeys[j].endsWith("CurrentCount");
|
|
918
917
|
let bDeferredCount = statskeys[j].endsWith("DeferredCount");
|
|
918
|
+
let bRescheduledCount = statskeys[j].endsWith("RescheduledCount");
|
|
919
919
|
if (statskeys[j].startsWith("Reader")) {
|
|
920
920
|
// parse tid from Reader key
|
|
921
921
|
let tidRegexp = /Reader\/TID:(.+)\/TotalCount/;
|
|
922
922
|
if (bCurrentCount) tidRegexp = /Reader\/TID:(.+)\/CurrentCount/;
|
|
923
923
|
if (bDeferredCount) tidRegexp = /Reader\/TID:(.+)\/DeferredCount/;
|
|
924
|
+
if (bRescheduledCount) tidRegexp = /Reader\/TID:(.+)\/RescheduledCount/;
|
|
924
925
|
let matchTID = statskeys[j].match(tidRegexp);
|
|
925
926
|
if (matchTID == null) {
|
|
926
927
|
console.log(`tid not found in ${statskeys[j]}.`);
|
|
@@ -945,6 +946,7 @@ export class BatchArray {
|
|
|
945
946
|
let tidRegexp = /Writer\/TID:(.+)\/TotalCount/;
|
|
946
947
|
if (bCurrentCount) tidRegexp = /Writer\/TID:(.+)\/CurrentCount/;
|
|
947
948
|
if (bDeferredCount) tidRegexp = /Writer\/TID:(.+)\/DeferredCount/;
|
|
949
|
+
if (bRescheduledCount) tidRegexp = /Writer\/TID:(.+)\/RescheduledCount/;
|
|
948
950
|
let matchTID = statskeys[j].match(tidRegexp);
|
|
949
951
|
if (matchTID == null) {
|
|
950
952
|
console.log(`tid not found in ${statskeys[j]}.`);
|
|
@@ -968,7 +970,7 @@ export class BatchArray {
|
|
|
968
970
|
writerNode.written = Math.max(Number(statsvalues[j]), writerNode.written);
|
|
969
971
|
console.log(`----- ${writerNode.name} Total Written: ${writerNode.written}`);
|
|
970
972
|
}
|
|
971
|
-
else if (bDeferredCount) {
|
|
973
|
+
else if (bDeferredCount || bRescheduledCount) {
|
|
972
974
|
writerNode.deferred = Math.max(Number(statsvalues[j]), writerNode.deferred);
|
|
973
975
|
console.log(`----- ${writerNode.name} Total Deferred: ${writerNode.deferred}`);
|
|
974
976
|
}
|
|
@@ -1181,6 +1183,9 @@ export function signIn(user: User, tasks: TaskArray): void {
|
|
|
1181
1183
|
}
|
|
1182
1184
|
export function signInIncrementally(user: User, scope: string): void {
|
|
1183
1185
|
if (user.oid == "1") return;
|
|
1186
|
+
//
|
|
1187
|
+
// for delegated permissions, we can use the Microsoft Identity Web Account Controller Challenge method
|
|
1188
|
+
//
|
|
1184
1189
|
let tenantURL: string = window.location.href;
|
|
1185
1190
|
tenantURL += "MicrosoftIdentity/Account/Challenge";
|
|
1186
1191
|
let url: URL = new URL(tenantURL);
|
|
@@ -1190,6 +1195,31 @@ export function signInIncrementally(user: User, scope: string): void {
|
|
|
1190
1195
|
url.searchParams.append("loginHint", user.mail);
|
|
1191
1196
|
window.location.assign(url.href);
|
|
1192
1197
|
}
|
|
1198
|
+
export function requestAdminConsent(user: User, scope: string): void {
|
|
1199
|
+
if (user.oid == "1") return;
|
|
1200
|
+
//
|
|
1201
|
+
// for app permissions (app roles) we must use the /.default scope for admin consent
|
|
1202
|
+
// https://learn.microsoft.com/EN-US/azure/active-directory/develop/v2-admin-consent#:~:text=In%20order%20to%20request%20app%20permissions%2C%20you%20must%20use%20the%20/.default%20value.
|
|
1203
|
+
// https://learn.microsoft.com/en-us/answers/questions/431784/how-to-grant-application-permissions-with-dynamic
|
|
1204
|
+
//
|
|
1205
|
+
// this means that, if we want to be granular about SyncReader vs. SyncWriter permissions, we must have separate Applications
|
|
1206
|
+
// for now, we request the /.default scope whenever any of the SyncReader or SyncWriter permissions are requested
|
|
1207
|
+
//
|
|
1208
|
+
// trying to use the Challenge endpoint for app permissions, setting this scope caused the call to quietly fail without error
|
|
1209
|
+
// scope = "63100afe-506e-4bb2-8ff7-d8d5ab373129/.default";
|
|
1210
|
+
//
|
|
1211
|
+
// thereforce, we are assuming that, for app permissions (app roles), the Microsoft Identity Web Challenge endpoint does not work and we need to perform our own redirect to the admin consent endpoint
|
|
1212
|
+
// https://learn.microsoft.com/EN-US/azure/active-directory/develop/scopes-oidc#client-credentials-grant-flow-and-default
|
|
1213
|
+
// https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#request-the-permissions-from-a-directory-admin
|
|
1214
|
+
//
|
|
1215
|
+
let adminConsentURL: string = "https://login.microsoftonline.com/";
|
|
1216
|
+
adminConsentURL += user.tid;
|
|
1217
|
+
adminConsentURL += "/adminconsent";
|
|
1218
|
+
let url: URL = new URL(adminConsentURL);
|
|
1219
|
+
url.searchParams.append("client_id", "63100afe-506e-4bb2-8ff7-d8d5ab373129");
|
|
1220
|
+
url.searchParams.append("redirectUri", window.location.origin);
|
|
1221
|
+
window.location.assign(url.href);
|
|
1222
|
+
}
|
|
1193
1223
|
export async function signOut(user: User): Promise<boolean>{
|
|
1194
1224
|
if (user.oid == "1") return;
|
|
1195
1225
|
// set logout_hint in the .NET session for streamlined logout
|
|
@@ -1557,7 +1587,7 @@ function processReturnedAdmins(workspace: Workspace, ii: InitInfo, returnedAdmin
|
|
|
1557
1587
|
}
|
|
1558
1588
|
// refresh all the data available from the server
|
|
1559
1589
|
user.oid = item.userId ? item.userId : item.email;
|
|
1560
|
-
user.name = item.firstName;
|
|
1590
|
+
user.name = item.firstName ?? user.name;
|
|
1561
1591
|
user.mail = item.email;
|
|
1562
1592
|
user.tid = item.tenantId;
|
|
1563
1593
|
// ensure this workspace tracks this user
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindline/sync",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.49",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"exports": "./index.ts",
|
|
7
7
|
"description": "sync is a node.js package encapsulating javscript classes required for configuring Mindline sync service.",
|
package/tasks.ts
CHANGED
|
@@ -26,14 +26,6 @@ const data: any[] = [
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
id: 4,
|
|
29
|
-
task: "PUT tenant",
|
|
30
|
-
start: "1970-01-01T00:00:00",
|
|
31
|
-
end: "1970-01-01T00:00:00",
|
|
32
|
-
expected: "0:01",
|
|
33
|
-
status: "not started"
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
id: 5,
|
|
37
29
|
task: "GET tenant details",
|
|
38
30
|
start: "1970-01-01T00:00:00",
|
|
39
31
|
end: "1970-01-01T00:00:00",
|
|
@@ -41,7 +33,7 @@ const data: any[] = [
|
|
|
41
33
|
status: "not started"
|
|
42
34
|
},
|
|
43
35
|
{
|
|
44
|
-
id:
|
|
36
|
+
id: 5,
|
|
45
37
|
task: "POST config init",
|
|
46
38
|
start: "1970-01-01T00:00:00",
|
|
47
39
|
end: "1970-01-01T00:00:00",
|
|
@@ -49,7 +41,7 @@ const data: any[] = [
|
|
|
49
41
|
status: "not started"
|
|
50
42
|
},
|
|
51
43
|
{
|
|
52
|
-
id:
|
|
44
|
+
id: 6,
|
|
53
45
|
task: "GET workspaces",
|
|
54
46
|
start: "1970-01-01T00:00:00",
|
|
55
47
|
end: "1970-01-01T00:00:00",
|
|
Binary file
|