@mindline/sync 1.0.40 → 1.0.42
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 -0
- package/.vs/slnx.sqlite +0 -0
- package/.vs/sync/FileContentIndex/9f8422ce-7c66-4297-9964-e1ce6180fd31.vsidx +0 -0
- package/.vs/sync/v17/.wsuo +0 -0
- package/index.d.ts +4 -2
- package/index.ts +96 -56
- package/package.json +1 -1
- package/tasks.ts +1 -1
- package/.vs/sync/FileContentIndex/3c52ebf8-d230-4ed9-9ae5-5c65a3630f6a.vsidx +0 -0
package/.vs/slnx.sqlite
CHANGED
|
Binary file
|
package/.vs/sync/v17/.wsuo
CHANGED
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ declare module "@mindline/sync" {
|
|
|
26
26
|
loginHint: string;
|
|
27
27
|
scopes: string[];
|
|
28
28
|
authTS: Date;
|
|
29
|
+
claimsprincipal: string; // claims principal cached at login to allow clearing cache at logout
|
|
29
30
|
constructor();
|
|
30
31
|
}
|
|
31
32
|
// tenant (Azure AD tenant, AD domain, Google workspace)
|
|
@@ -104,7 +105,7 @@ declare module "@mindline/sync" {
|
|
|
104
105
|
export type TaskType = "initialization" |
|
|
105
106
|
"authenticate user" |
|
|
106
107
|
"reload React" |
|
|
107
|
-
"PUT
|
|
108
|
+
"PUT tenant" |
|
|
108
109
|
"GET tenant details" |
|
|
109
110
|
"POST config init" |
|
|
110
111
|
"GET workspaces" |
|
|
@@ -203,6 +204,7 @@ declare module "@mindline/sync" {
|
|
|
203
204
|
read: number;
|
|
204
205
|
written: number;
|
|
205
206
|
deferred: number;
|
|
207
|
+
nothingtosync: boolean;
|
|
206
208
|
targets: TenantNode[];
|
|
207
209
|
constructor(tid: string, name: string);
|
|
208
210
|
update(total: number, read: number, written: number, deferred: number): void;
|
|
@@ -220,7 +222,7 @@ declare module "@mindline/sync" {
|
|
|
220
222
|
export function groupsGet(instance: IPublicClientApplication, user: User | undefined, groupSearchString: string): Promise<{groups: Group[], error: string}>;
|
|
221
223
|
export function signIn(user: User, tasks: TaskArray): void;
|
|
222
224
|
export function signInIncrementally(user: User, scope: string): void;
|
|
223
|
-
export function signOut(user: User):
|
|
225
|
+
export function signOut(user: User): boolean;
|
|
224
226
|
export function tenantRelationshipsGetByDomain(loggedInuser: User, tenant: Tenant, instance: IPublicClientApplication, debug: boolean): boolean;
|
|
225
227
|
export function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, tasks: TaskArray, debug: boolean): boolean;
|
|
226
228
|
export function tenantUnauthenticatedLookup(tenant: Tenant, debug: boolean): Promise<boolean>;
|
package/index.ts
CHANGED
|
@@ -732,22 +732,32 @@ export class BatchArray {
|
|
|
732
732
|
this.pb_idleMax = 0;
|
|
733
733
|
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}]`);
|
|
734
734
|
this.pb_timer = setInterval(() => {
|
|
735
|
-
// if
|
|
736
|
-
this.
|
|
737
|
-
this.pb_idleMax = Math.max(this.pb_idle, this.pb_idleMax);
|
|
738
|
-
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}]`);
|
|
739
|
-
if (this.pb_idle >= 20) {
|
|
735
|
+
// if signalR has finished the sync, stop the timer
|
|
736
|
+
if (this.milestoneArray.milestones[0].Write != null) {
|
|
740
737
|
clearInterval(this.pb_timer);
|
|
741
738
|
this.pb_timer = null;
|
|
742
|
-
|
|
743
|
-
this.milestoneArray.write(setMilestones);
|
|
744
|
-
}
|
|
745
|
-
setConfigSyncResult(`finished sync, no updates for ${this.pb_idle} seconds`);
|
|
746
|
-
}
|
|
747
|
-
// if we get to 100, stop the timer, let SignalR or countdown timer finish sync
|
|
748
|
-
if (this.pb_progress < 100) {
|
|
749
|
-
this.pb_progress = Math.min(100, this.pb_progress + this.pb_increment);
|
|
739
|
+
this.pb_progress = 100;
|
|
750
740
|
setSyncProgress(this.pb_progress);
|
|
741
|
+
setIdleText(`Complete. [max idle: ${this.pb_idleMax}]`);
|
|
742
|
+
}
|
|
743
|
+
else {
|
|
744
|
+
// if we've gone 30 seconds without a signalR message, finish the sync
|
|
745
|
+
this.pb_idle = this.pb_idle + 1;
|
|
746
|
+
this.pb_idleMax = Math.max(this.pb_idle, this.pb_idleMax);
|
|
747
|
+
setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}]`);
|
|
748
|
+
if (this.pb_idle >= 60) {
|
|
749
|
+
clearInterval(this.pb_timer);
|
|
750
|
+
this.pb_timer = null;
|
|
751
|
+
if (this.milestoneArray.milestones[0].Write == null) {
|
|
752
|
+
this.milestoneArray.write(setMilestones);
|
|
753
|
+
setConfigSyncResult(`finished sync, no updates for ${this.pb_idle} seconds`);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
// if we get to 100, the progress bar stops but SignalR or countdown timer completes the sync
|
|
757
|
+
if (this.pb_progress < 100) {
|
|
758
|
+
this.pb_progress = Math.min(100, this.pb_progress + this.pb_increment);
|
|
759
|
+
setSyncProgress(this.pb_progress);
|
|
760
|
+
}
|
|
751
761
|
}
|
|
752
762
|
}, 1000);
|
|
753
763
|
this.milestoneArray.start(setMilestones);
|
|
@@ -803,10 +813,13 @@ export class BatchArray {
|
|
|
803
813
|
return;
|
|
804
814
|
}
|
|
805
815
|
tenantNode.batchId = matchingPair.BatchId;
|
|
806
|
-
// process stats for this SignalR message batch
|
|
816
|
+
// process stats for this SignalR message (one batch per tenant node)
|
|
807
817
|
let statsarray = item.Stats; // get the array of statistics
|
|
808
818
|
let statskeys = Object.keys(statsarray); // get the keys of the array
|
|
809
819
|
let statsvalues = Object.values(statsarray); // get the values of the array
|
|
820
|
+
// does this tenantnode/batch have nothing to sync?
|
|
821
|
+
let bTotalCountZero: boolean = false;
|
|
822
|
+
let bCurrentCountZero: boolean = false;
|
|
810
823
|
for (let j = 0; j < statskeys.length; j++) {
|
|
811
824
|
let bTotalCount = statskeys[j].endsWith("TotalCount");
|
|
812
825
|
let bCurrentCount = statskeys[j].endsWith("CurrentCount");
|
|
@@ -823,15 +836,18 @@ export class BatchArray {
|
|
|
823
836
|
return;
|
|
824
837
|
}
|
|
825
838
|
if (bTotalCount) {
|
|
839
|
+
bTotalCountZero = Number(statsvalues[j]) == 0;
|
|
826
840
|
tenantNode.total = Math.max(Number(statsvalues[j]), tenantNode.total);
|
|
827
841
|
console.log(`----- ${tenantNode.name} TID: ${tenantNode.tid} batchId: ${tenantNode.batchId}`);
|
|
828
842
|
console.log(`----- ${tenantNode.name} Total To Read: ${tenantNode.total}`);
|
|
829
843
|
}
|
|
830
844
|
else {
|
|
845
|
+
bCurrentCountZero = Number(statsvalues[j]) == 0;
|
|
831
846
|
tenantNode.read = Math.max(Number(statsvalues[j]), tenantNode.read);
|
|
832
847
|
console.log(`----- ${tenantNode.name} Currently Read: ${tenantNode.read}`);
|
|
833
848
|
}
|
|
834
849
|
}
|
|
850
|
+
tenantNode.nothingtosync = bTotalCountZero && bCurrentCountZero;
|
|
835
851
|
if (statskeys[j].startsWith("Writer")) {
|
|
836
852
|
// parse tid from Writer key
|
|
837
853
|
let tidRegexp = /Writer\/TID:(.+)\/TotalCount/;
|
|
@@ -878,6 +894,7 @@ export class BatchArray {
|
|
|
878
894
|
let bReadingComplete: boolean = true;
|
|
879
895
|
let bWritingComplete: boolean = true;
|
|
880
896
|
let bWritingStarted: boolean = false;
|
|
897
|
+
let bNothingToSync: boolean = true;
|
|
881
898
|
let readerTotal: number = 0;
|
|
882
899
|
let readerCurrent: number = 0;
|
|
883
900
|
let writerTotal: number = 0;
|
|
@@ -889,6 +906,7 @@ export class BatchArray {
|
|
|
889
906
|
writerTotal += Math.max(writerNode.total, sourceTenantNode.total);
|
|
890
907
|
writerCurrent += writerNode.written;
|
|
891
908
|
});
|
|
909
|
+
bNothingToSync &&= sourceTenantNode.nothingtosync;
|
|
892
910
|
bReadingComplete &&= (sourceTenantNode.status == "complete" || sourceTenantNode.status == "failed");
|
|
893
911
|
readerTotal += sourceTenantNode.total;
|
|
894
912
|
readerCurrent += sourceTenantNode.read;
|
|
@@ -898,37 +916,44 @@ export class BatchArray {
|
|
|
898
916
|
setReadersCurrent(readerCurrent);
|
|
899
917
|
setWritersTotal(Math.max(writerTotal, readerTotal));
|
|
900
918
|
setWritersCurrent(writerCurrent);
|
|
901
|
-
//
|
|
902
|
-
if (
|
|
903
|
-
this.milestoneArray.read(setMilestones);
|
|
904
|
-
setConfigSyncResult("reading complete");
|
|
905
|
-
console.log(`Setting config sync result: "reading complete"`);
|
|
906
|
-
// trigger refresh delta tokens
|
|
907
|
-
setRefreshDeltaTrigger(true);
|
|
908
|
-
// change to % per second to complete in 7x as long as it took to get here
|
|
909
|
-
let readTS = Date.now();
|
|
910
|
-
let secsElapsed = (readTS - this.pb_startTS) / 1000;
|
|
911
|
-
let expectedPercentDone = 7;
|
|
912
|
-
let expectedPercentPerSecond = secsElapsed / expectedPercentDone;
|
|
913
|
-
this.pb_increment = expectedPercentPerSecond;
|
|
914
|
-
console.log(`Setting increment: ${this.pb_increment}% per second`);
|
|
915
|
-
}
|
|
916
|
-
// with that out of the way, is writing complete?
|
|
917
|
-
if (bWritingComplete) {
|
|
919
|
+
// check to see if there was nothing to sync
|
|
920
|
+
if (bNothingToSync) {
|
|
918
921
|
this.milestoneArray.write(setMilestones);
|
|
919
|
-
setConfigSyncResult("sync
|
|
920
|
-
console.log(`Setting config sync result: "
|
|
921
|
-
this.pb_progress = 99;
|
|
922
|
+
setConfigSyncResult("nothing to sync");
|
|
923
|
+
console.log(`Setting config sync result: "nothing to sync"`);
|
|
922
924
|
}
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
925
|
+
else {
|
|
926
|
+
// because it is an important milestone, we always check if we have *just* completed reading
|
|
927
|
+
if (bReadingComplete && this.milestoneArray.milestones[0].Read == null) {
|
|
928
|
+
this.milestoneArray.read(setMilestones);
|
|
929
|
+
setConfigSyncResult("reading complete");
|
|
930
|
+
console.log(`Setting config sync result: "reading complete"`);
|
|
931
|
+
// trigger refresh delta tokens
|
|
932
|
+
setRefreshDeltaTrigger(true);
|
|
933
|
+
// change to % per second to complete in 7x as long as it took to get here
|
|
934
|
+
let readTS = Date.now();
|
|
935
|
+
let secsElapsed = (readTS - this.pb_startTS) / 1000;
|
|
936
|
+
let expectedPercentDone = 7;
|
|
937
|
+
let expectedPercentPerSecond = secsElapsed / expectedPercentDone;
|
|
938
|
+
this.pb_increment = expectedPercentPerSecond;
|
|
939
|
+
console.log(`Setting increment: ${this.pb_increment}% per second`);
|
|
940
|
+
}
|
|
941
|
+
// with that out of the way, is writing complete?
|
|
942
|
+
if (bWritingComplete) {
|
|
943
|
+
this.milestoneArray.write(setMilestones);
|
|
944
|
+
setConfigSyncResult("sync complete");
|
|
945
|
+
console.log(`Setting config sync result: "complete"`);
|
|
946
|
+
}
|
|
947
|
+
// if not, has writing even started?
|
|
948
|
+
else if (bWritingStarted) {
|
|
949
|
+
setConfigSyncResult("writing in progress");
|
|
950
|
+
console.log(`Setting config sync result: "writing in progress"`);
|
|
951
|
+
}
|
|
952
|
+
// else, we must be reading (unless we already completed reading)
|
|
953
|
+
else if (this.milestoneArray.milestones[0].Read == null) {
|
|
954
|
+
setConfigSyncResult("reading in progress");
|
|
955
|
+
console.log(`Setting config sync result: "reading in progress"`);
|
|
956
|
+
}
|
|
932
957
|
}
|
|
933
958
|
}
|
|
934
959
|
// start SignalR connection based on each batchId
|
|
@@ -986,12 +1011,14 @@ export class TenantNode {
|
|
|
986
1011
|
read: number;
|
|
987
1012
|
written: number;
|
|
988
1013
|
deferred: number;
|
|
1014
|
+
nothingtosync: boolean;
|
|
989
1015
|
targets: TenantNode[];
|
|
990
1016
|
constructor(tid: string, name: string, batchId: string) {
|
|
991
1017
|
this.expanded = false;
|
|
992
1018
|
this.name = name;
|
|
993
1019
|
this.tid = tid;
|
|
994
1020
|
this.batchId = batchId;
|
|
1021
|
+
this.nothingtosync = false;
|
|
995
1022
|
this.targets = new Array<TenantNode>();
|
|
996
1023
|
this.update(0, 0, 0, 0);
|
|
997
1024
|
}
|
|
@@ -1047,11 +1074,11 @@ export async function groupsGet(instance: IPublicClientApplication, user: User |
|
|
|
1047
1074
|
}
|
|
1048
1075
|
}
|
|
1049
1076
|
export function signIn(user: User, tasks: TaskArray): void {
|
|
1077
|
+
// SignIn by an admin consents the full set of permissions, unlike Challenge which requires a consented app
|
|
1050
1078
|
let tenantURL: string = window.location.href;
|
|
1051
|
-
tenantURL += "MicrosoftIdentity/Account/
|
|
1079
|
+
tenantURL += "MicrosoftIdentity/Account/SignIn";
|
|
1052
1080
|
let url: URL = new URL(tenantURL);
|
|
1053
1081
|
url.searchParams.append("redirectUri", window.location.origin);
|
|
1054
|
-
url.searchParams.append("scope", "openid offline_access Directory.AccessAsUser.All CrossTenantInformation.ReadBasic.All");
|
|
1055
1082
|
url.searchParams.append("domainHint", "organizations");
|
|
1056
1083
|
if (user.oid !== "1") {
|
|
1057
1084
|
url.searchParams.append("loginHint", user.mail);
|
|
@@ -1072,18 +1099,31 @@ export function signInIncrementally(user: User, scope: string): void {
|
|
|
1072
1099
|
url.searchParams.append("loginHint", user.mail);
|
|
1073
1100
|
window.location.assign(url.href);
|
|
1074
1101
|
}
|
|
1075
|
-
export function signOut(user: User):
|
|
1102
|
+
export async function signOut(user: User): Promise<boolean>{
|
|
1076
1103
|
if (user.oid == "1") return;
|
|
1077
|
-
//
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
url.searchParams.append("
|
|
1085
|
-
|
|
1086
|
-
|
|
1104
|
+
// set logout_hint in the .NET session for streamlined logout
|
|
1105
|
+
let userEndpoint: string = window.location.href;
|
|
1106
|
+
userEndpoint += "user";
|
|
1107
|
+
let url = new URL(userEndpoint);
|
|
1108
|
+
url.searchParams.append("oid", user.oid);
|
|
1109
|
+
url.searchParams.append("tid", user.tid);
|
|
1110
|
+
url.searchParams.append("loginHint", user.loginHint);
|
|
1111
|
+
url.searchParams.append("verb", "LOGOUT");
|
|
1112
|
+
let options = { method: "PATCH" };
|
|
1113
|
+
let userLogoutResponse: Response = await fetch(url.href, options);
|
|
1114
|
+
if (userLogoutResponse.status == 200 && userLogoutResponse.statusText == "OK") {
|
|
1115
|
+
console.log(`Successfully set admin ${user.mail} logout_hint`);
|
|
1116
|
+
}
|
|
1117
|
+
else {
|
|
1118
|
+
console.log(`Failed to set admin ${user.mail} logout_hint`);
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
// start the logout process triggering callbacks during logout
|
|
1122
|
+
// OnRedirectToIdentityProviderForSignOut - this is where we set the logout_hint for user we are trying to logout
|
|
1123
|
+
// OnSignedOutCallbackRedirect - called when the call sucessfully completes
|
|
1124
|
+
let signoutURL: string = window.location.href;
|
|
1125
|
+
signoutURL += "MicrosoftIdentity/Account/SignOut";
|
|
1126
|
+
window.location.assign(signoutURL);
|
|
1087
1127
|
}
|
|
1088
1128
|
//tenantRelationshipsGetByDomain - query AAD for associated company name and id
|
|
1089
1129
|
export async function tenantRelationshipsGetByDomain(loggedInUser: User, tenant: Tenant, instance: IPublicClientApplication, debug: boolean): Promise<boolean> {
|
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.42",
|
|
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
|
Binary file
|