@mindline/sync 1.0.55 → 1.0.57

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/slnx.sqlite CHANGED
Binary file
Binary file
package/index.d.ts CHANGED
@@ -223,6 +223,7 @@ declare module "@mindline/sync" {
223
223
  pb_increment: number;
224
224
  pb_idle: number;
225
225
  pb_idleMax: number;
226
+ pb_total: number;
226
227
  pb_timer: NodeJS.Timer;
227
228
  milestoneArray: MilestoneArray;
228
229
  constructor(config: Config|null, syncPortalGlobalState: InitInfo|null, bClearLocalStorage: boolean);
@@ -263,7 +264,7 @@ declare module "@mindline/sync" {
263
264
  // Azure AD Graph API
264
265
  //
265
266
  export function groupsGet(instance: IPublicClientApplication, user: User | undefined, groupSearchString: string): Promise<{groups: Group[], error: string}>;
266
- export function signIn(user: User, tasks: TaskArray): void;
267
+ export function signIn(user: User, tasks: TaskArray): boolean;
267
268
  export function signInIncrementally(user: User, scope: string): void;
268
269
  export function requestAdminConsent(user: User, scope: string): void;
269
270
  export function signOut(user: User): boolean;
package/index.ts CHANGED
@@ -337,14 +337,11 @@ export class InitInfo {
337
337
  } else {
338
338
  // we should not have InitInfo missing Workspace components
339
339
  debugger;
340
- return false;
341
340
  }
342
341
  }
343
342
  // find matching Tenants to tag with this workspace
344
343
  for (let tenantID of workspace.associatedTenants) {
345
- let tenant = this.ts.find(
346
- (currentTenant) => currentTenant.tid === tenantID
347
- );
344
+ let tenant = this.ts.find((currentTenant) => currentTenant.tid === tenantID);
348
345
  if (tenant !== undefined) {
349
346
  // we found the tenant
350
347
  tenant[FILTER_FIELD] += workspace.id;
@@ -352,14 +349,11 @@ export class InitInfo {
352
349
  } else {
353
350
  // we should not have InitInfo missing Workspace components
354
351
  debugger;
355
- return false;
356
352
  }
357
353
  }
358
354
  // find matching Configs to tag with this workspace
359
355
  for (let configID of workspace.associatedConfigs) {
360
- let config = this.cs.find(
361
- (currentConfig) => currentConfig.id === configID
362
- );
356
+ let config = this.cs.find((currentConfig) => currentConfig.id === configID);
363
357
  if (config !== undefined) {
364
358
  // we found the config
365
359
  config[FILTER_FIELD] += workspace.id;
@@ -367,7 +361,6 @@ export class InitInfo {
367
361
  } else {
368
362
  // we should not have InitInfo missing Workspace components
369
363
  debugger;
370
- return false;
371
364
  }
372
365
  }
373
366
  }
@@ -781,6 +774,7 @@ export class BatchArray {
781
774
  pb_increment: number;
782
775
  pb_idle: number;
783
776
  pb_idleMax: number;
777
+ pb_total: number;
784
778
  pb_timer: NodeJS.Timer;
785
779
  milestoneArray: MilestoneArray;
786
780
  constructor(
@@ -796,6 +790,7 @@ export class BatchArray {
796
790
  this.pb_timer = null;
797
791
  this.pb_idle = 0;
798
792
  this.pb_idleMax = 0;
793
+ this.pb_total = 0;
799
794
  this.milestoneArray = new MilestoneArray(false);
800
795
  }
801
796
  // populate tenantNodes based on config tenants
@@ -885,7 +880,7 @@ export class BatchArray {
885
880
  this.pb_increment = .25;
886
881
  this.pb_idle = 0;
887
882
  this.pb_idleMax = 0;
888
- setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}/60]`);
883
+ this.pb_total = 0;
889
884
  this.pb_timer = setInterval(() => {
890
885
  // if signalR has finished the sync, stop the timer
891
886
  if (this.milestoneArray.milestones[0].Write != null) {
@@ -897,9 +892,10 @@ export class BatchArray {
897
892
  }
898
893
  else {
899
894
  // if we've gone 60 seconds without a signalR message, finish the sync
895
+ this.pb_total = this.pb_total + 1;
900
896
  this.pb_idle = this.pb_idle + 1;
901
897
  this.pb_idleMax = Math.max(this.pb_idle, this.pb_idleMax);
902
- setIdleText(`No updates seen for ${this.pb_idle} seconds. [max idle: ${this.pb_idleMax}/60]`);
898
+ setIdleText(`${this.pb_total} seconds elapsed. Last update ${this.pb_idle} seconds ago. [max idle: ${this.pb_idleMax}/60]`);
903
899
  if (this.pb_idle >= 60) {
904
900
  clearInterval(this.pb_timer);
905
901
  this.pb_timer = null;
@@ -1226,22 +1222,38 @@ export async function groupsGet(instance: IPublicClientApplication, user: User |
1226
1222
  return { groups: [], error: `Exception: ${error}` };
1227
1223
  }
1228
1224
  }
1229
- export async function signIn(user: User, tasks: TaskArray): void {
1225
+ export async function signIn(user: User, tasks: TaskArray): Promise<boolean> {
1226
+ // admin authority is blank at signIn, lookup authority real-time
1227
+ if (user.authority == "") {
1228
+ // lookup authority for this user (the lookup call does it based on domain, but TID works as well to find authority)
1229
+ let tenant: Tenant = new Tenant();
1230
+ tenant.domain = user.tid;
1231
+ let bResult: boolean = await tenantUnauthenticatedLookup(tenant, false);
1232
+ if (bResult) {
1233
+ // success, we now know cloud instance where this tenant is provisioned
1234
+ user.authority = tenant.authority;
1235
+ }
1236
+ else {
1237
+ // can't sign in without an authority
1238
+ debugger;
1239
+ return false;
1240
+ }
1241
+ }
1230
1242
  switch (user.authority) {
1231
1243
  case graphConfig.authorityWW:
1232
- // SignIn by an admin consents more permissions than Challenge which requires a consented app
1244
+ // SignIn by an admin consents the app, Challenge adds incremental permissions dynamically, but requires a consented app
1233
1245
  let tenantURL: string = window.location.href;
1234
1246
  tenantURL += "MicrosoftIdentity/Account/SignIn";
1235
1247
  let url: URL = new URL(tenantURL);
1236
1248
  url.searchParams.append("redirectUri", window.location.origin);
1237
1249
  url.searchParams.append("domainHint", "organizations");
1238
- if (user.oid !== "1") {
1250
+ if (user.oid !== "1") { // "1" means no mail has been set by admin initially in the app, oid and mail should be same if user has set and not yet signed in
1239
1251
  url.searchParams.append("loginHint", user.mail);
1240
1252
  }
1241
1253
  tasks.setTaskStart("initialization", new Date());
1242
1254
  tasks.setTaskStart("authenticate user", new Date());
1243
1255
  window.location.assign(url.href);
1244
- break;
1256
+ return true;
1245
1257
  case graphConfig.authorityUS:
1246
1258
  // retrieve controller protected by USGov authorization
1247
1259
  let usURL: string = window.location.href;
@@ -1255,13 +1267,15 @@ export async function signIn(user: User, tasks: TaskArray): void {
1255
1267
  tasks.setTaskStart("initialization", new Date());
1256
1268
  tasks.setTaskStart("authenticate user", new Date());
1257
1269
  window.location.assign(urlUS.href);
1258
- break;
1270
+ return true;
1259
1271
  case graphConfig.authorityCN:
1260
1272
  // unsupported
1261
1273
  break;
1262
1274
  default:
1275
+ // unknown authority
1263
1276
  debugger;
1264
1277
  }
1278
+ return false;
1265
1279
  }
1266
1280
  export function signInIncrementally(user: User, scope: string): void {
1267
1281
  if (user.oid == "1") return;
@@ -1304,7 +1318,7 @@ export function requestAdminConsent(user: User, scope: string): void {
1304
1318
  window.location.assign(url.href);
1305
1319
  }
1306
1320
  export async function signOut(user: User): Promise<boolean>{
1307
- if (user.oid == "1") return;
1321
+ if (user.oid == "1") return false;
1308
1322
  // set logout_hint in the .NET session for streamlined logout
1309
1323
  let userEndpoint: string = window.location.href;
1310
1324
  userEndpoint += "user";
@@ -1320,7 +1334,7 @@ export async function signOut(user: User): Promise<boolean>{
1320
1334
  }
1321
1335
  else {
1322
1336
  console.log(`Failed to set admin ${user.mail} logout_hint`);
1323
- return;
1337
+ return false;
1324
1338
  }
1325
1339
  // start the logout process triggering callbacks during logout
1326
1340
  // OnRedirectToIdentityProviderForSignOut - this is where we set the logout_hint for user we are trying to logout
@@ -1328,6 +1342,7 @@ export async function signOut(user: User): Promise<boolean>{
1328
1342
  let signoutURL: string = window.location.href;
1329
1343
  signoutURL += "MicrosoftIdentity/Account/SignOut";
1330
1344
  window.location.assign(signoutURL);
1345
+ return true;
1331
1346
  }
1332
1347
  //tenantRelationshipsGetByDomain - query AAD for associated company name and id
1333
1348
  export async function tenantRelationshipsGetByDomain(loggedInUser: User, tenant: Tenant, instance: IPublicClientApplication, debug: boolean): Promise<boolean> {
@@ -1667,6 +1682,17 @@ function processReturnedAdmins(workspace: Workspace, ii: InitInfo, returnedAdmin
1667
1682
  user.name = item.firstName ?? user.name;
1668
1683
  user.mail = item.email;
1669
1684
  user.tid = item.tenantId;
1685
+ // *try* to set authority from tenant returned in previous call processReturnedTenants (it may not be there)
1686
+ // ASSUMPTION: user either comes from
1687
+ // 1. .NET session, in which case user has an authority from the token
1688
+ // 2. Config API, in which case either
1689
+ // a. associated tenant with authority exists for this user (i.e. workspace owner has called POST init/configuration and created Admin and Tenant at same time)
1690
+ // b. user has never logged in (i.e. workspace owner has invited an incomplete admin to the workspace and there is no corresponding tenant)
1691
+ // i. this means that we *may* not have an authority stored for this user
1692
+ let tenant: Tenant | undefined = ii.ts.find((t) => (t.tid === user.tid));
1693
+ if (tenant != undefined) {
1694
+ user.authority = tenant.authority;
1695
+ }
1670
1696
  // ensure this workspace tracks this user
1671
1697
  let idx = workspace.associatedUsers.findIndex((u) => u === user.oid);
1672
1698
  if (idx == -1) workspace.associatedUsers.push(user.oid);
@@ -1813,9 +1839,9 @@ async function workspaceInfoGet(instance: IPublicClientApplication, authorizedUs
1813
1839
  if (!adminsResult.result) return adminsResult;
1814
1840
  if (!tenantsResult.result) return tenantsResult;
1815
1841
  if (!configsResult.result) return configsResult;
1816
- // process returned workspace components
1817
- processReturnedAdmins(workspace, ii, adminsResult.array!);
1842
+ // process returned workspace components (tenants first as they have the authorities that admins depend on)
1818
1843
  processReturnedTenants(workspace, ii, tenantsResult.array!);
1844
+ processReturnedAdmins(workspace, ii, adminsResult.array!);
1819
1845
  processReturnedConfigs(workspace, ii, configsResult.array!);
1820
1846
  // tag components with workspaceIDs
1821
1847
  ii.tagWithWorkspaces();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mindline/sync",
3
3
  "type": "module",
4
- "version": "1.0.55",
4
+ "version": "1.0.57",
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/users.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "oid": "1",
4
4
  "name": "",
5
5
  "mail": "",
6
- "authority": "",
6
+ "authority": "https://login.microsoftonline.com/",
7
7
  "tid": "",
8
8
  "companyName": "",
9
9
  "companyDomain": "",