@mindline/sync 1.0.66 → 1.0.68

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.
@@ -2,5 +2,6 @@
2
2
  "ExpandedNodes": [
3
3
  ""
4
4
  ],
5
+ "SelectedNode": "\\README.md",
5
6
  "PreviewInSolutionExplorer": false
6
7
  }
package/.vs/slnx.sqlite CHANGED
Binary file
Binary file
@@ -2,6 +2,14 @@
2
2
  "Version": 1,
3
3
  "WorkspaceRootPath": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\",
4
4
  "Documents": [
5
+ {
6
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\README.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}",
7
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:README.md||{EFC0BB08-EA7D-40C6-A696-C870411A895B}"
8
+ },
9
+ {
10
+ "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.d.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}",
11
+ "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:index.d.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}"
12
+ },
5
13
  {
6
14
  "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}",
7
15
  "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:index.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}"
@@ -9,10 +17,6 @@
9
17
  {
10
18
  "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\hybridspa.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}",
11
19
  "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:hybridspa.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}"
12
- },
13
- {
14
- "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.d.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}",
15
- "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:index.d.ts||{0F2454B1-A556-402D-A7D0-1FDE7F99DEE0}"
16
20
  }
17
21
  ],
18
22
  "DocumentGroupContainers": [
@@ -22,7 +26,7 @@
22
26
  "DocumentGroups": [
23
27
  {
24
28
  "DockedWidth": 179,
25
- "SelectedChildIndex": 10,
29
+ "SelectedChildIndex": -1,
26
30
  "Children": [
27
31
  {
28
32
  "$type": "Bookmark",
@@ -55,43 +59,62 @@
55
59
  {
56
60
  "$type": "Bookmark",
57
61
  "Name": "ST:1:0:{d212f56b-c48a-434c-a121-1c5d80b59b9f}"
62
+ }
63
+ ]
64
+ },
65
+ {
66
+ "DockedWidth": 200,
67
+ "SelectedChildIndex": 0,
68
+ "Children": [
69
+ {
70
+ "$type": "Document",
71
+ "DocumentIndex": 0,
72
+ "Title": "README.md",
73
+ "DocumentMoniker": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\README.md",
74
+ "RelativeDocumentMoniker": "README.md",
75
+ "ToolTip": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\README.md",
76
+ "RelativeToolTip": "README.md",
77
+ "ViewState": "AQIAAAAAAAAAAAAAAAAAABoAAAASAAAA",
78
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001818|",
79
+ "WhenOpened": "2024-01-05T21:52:59.93Z",
80
+ "EditorCaption": ""
58
81
  },
59
82
  {
60
83
  "$type": "Document",
61
84
  "DocumentIndex": 2,
85
+ "Title": "index.ts",
86
+ "DocumentMoniker": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.ts",
87
+ "RelativeDocumentMoniker": "index.ts",
88
+ "ToolTip": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.ts",
89
+ "RelativeToolTip": "index.ts",
90
+ "ViewState": "AQIAAMsGAAAAAAAAAAAvwDkHAAABAAAA",
91
+ "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003213|",
92
+ "WhenOpened": "2023-12-05T02:10:16.04Z"
93
+ },
94
+ {
95
+ "$type": "Document",
96
+ "DocumentIndex": 1,
62
97
  "Title": "index.d.ts",
63
98
  "DocumentMoniker": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.d.ts",
64
99
  "RelativeDocumentMoniker": "index.d.ts",
65
100
  "ToolTip": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.d.ts",
66
101
  "RelativeToolTip": "index.d.ts",
67
- "ViewState": "AQIAAP0AAAAAAAAAAAAhwA4BAABQAAAA",
102
+ "ViewState": "AQIAAAMBAAAAAAAAAEAwwC8BAAAoAAAA",
68
103
  "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003213|",
69
- "WhenOpened": "2023-11-25T03:36:49.251Z"
104
+ "WhenOpened": "2024-01-01T16:19:43.325Z",
105
+ "EditorCaption": ""
70
106
  },
71
107
  {
72
108
  "$type": "Document",
73
- "DocumentIndex": 1,
109
+ "DocumentIndex": 3,
74
110
  "Title": "hybridspa.ts",
75
111
  "DocumentMoniker": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\hybridspa.ts",
76
112
  "RelativeDocumentMoniker": "hybridspa.ts",
77
113
  "ToolTip": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\hybridspa.ts",
78
114
  "RelativeToolTip": "hybridspa.ts",
79
- "ViewState": "AQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
115
+ "ViewState": "AQIAAB8AAAAAAAAAAAAGwFUAAAAEAAAA",
80
116
  "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003213|",
81
117
  "WhenOpened": "2023-11-25T02:18:34.862Z"
82
- },
83
- {
84
- "$type": "Document",
85
- "DocumentIndex": 0,
86
- "Title": "index.ts",
87
- "DocumentMoniker": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.ts",
88
- "RelativeDocumentMoniker": "index.ts",
89
- "ToolTip": "C:\\Users\\ArvindSuthar\\source\\repos\\front\\sync\\index.ts",
90
- "RelativeToolTip": "index.ts",
91
- "ViewState": "AQIAAAAAAAAAAAAAAAAAAFAAAAAEAAAA",
92
- "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.003213|",
93
- "WhenOpened": "2023-11-25T04:05:46.842Z",
94
- "EditorCaption": ""
95
118
  }
96
119
  ]
97
120
  },
package/hybridspa.ts CHANGED
@@ -77,18 +77,11 @@ export async function adminDelete(
77
77
  result.status = 500;
78
78
  return result;
79
79
  }
80
- // are we performing deletion of a full admin?
80
+ // define admin endpoint and add workspaceId parameter
81
81
  let url: URL | null = null;
82
- if (user.oid !== user.mail) {
83
- url = new URL(mindlineConfig.adminEndpoint());
84
- url.searchParams.append("workspaceId", workspaceId);
85
- }
86
- // or of an incomplete admin?
87
- else if (user.mail !== "") {
88
- url = new URL(mindlineConfig.adminIncompleteEndpoint());
89
- url.searchParams.append("email", user.mail);
90
- url.searchParams.append("workspaceId", workspaceId);
91
- }
82
+ url = new URL(mindlineConfig.adminEndpoint());
83
+ url.searchParams.append("workspaceId", workspaceId);
84
+ url.searchParams.append("email", user.mail);
92
85
  // create headers
93
86
  const headers = await defineHeaders(instance, authorizedUser);
94
87
  // make endpoint call
@@ -768,6 +761,48 @@ export async function tenantPut(
768
761
  }
769
762
  return result;
770
763
  }
764
+ //workspacePut
765
+ export async function workspacePut(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult> {
766
+ let result: APIResult = new APIResult();
767
+ if (workspaceId == "" || workspaceName == "") {
768
+ result.result = false;
769
+ result.error = "workspacePut: invalid workspace ID or name";
770
+ result.status = 500;
771
+ return result;
772
+ }
773
+ // create parameterized workspace endpoint
774
+ let endpoint: string = mindlineConfig.workspaceEndpoint();
775
+ let url: URL = new URL(endpoint);
776
+ url.searchParams.append("workspaceId", workspaceId);
777
+ url.searchParams.append("workspaceName", workspaceName);
778
+ // create workspace headers
779
+ const headers = await defineHeaders(instance, authorizedUser);
780
+ let options = { method: "PUT", headers: headers };
781
+ // make config endpoint call
782
+ try {
783
+ console.log("Attempting PUT to /workspace: " + url.href);
784
+ let response = await fetch(url.href, options);
785
+ if (response.status === 200 && response.statusText === "OK") {
786
+ console.log(`Successful PUT to ${url.href}`);
787
+ return result;
788
+ }
789
+ else {
790
+ result.error = await processErrors(response);
791
+ console.log(`Failed PUT to ${url.href}`);
792
+ console.log(result.error);
793
+ result.status = 500;
794
+ result.result = false;
795
+ return result;
796
+ }
797
+ }
798
+ catch (error: any) {
799
+ result.error = error.message;
800
+ result.status = 500;
801
+ result.result = false;
802
+ console.log(error.message);
803
+ }
804
+ return result;
805
+ }
771
806
  //workspacesGet
772
807
  export async function workspacesGet(
773
808
  instance: IPublicClientApplication,
@@ -784,7 +819,7 @@ export async function workspacesGet(
784
819
  return result;
785
820
  }
786
821
  // create workspaces endpoint
787
- let endpoint: string = mindlineConfig.workspaceEndpoint();
822
+ let endpoint: string = mindlineConfig.workspacesEndpoint();
788
823
  // create workspace endpoint
789
824
  let url: URL = new URL(endpoint);
790
825
  // create workspace headers
package/index.d.ts CHANGED
@@ -24,6 +24,7 @@ declare module "@mindline/sync" {
24
24
  static tenantEndpoint(): string;
25
25
  static tenantsEndpoint(): string;
26
26
  static workspaceEndpoint(): string;
27
+ static workspacesEndpoint(): string;
27
28
  // SignalR endpoint
28
29
  static signalREndpoint(): string;
29
30
  }
@@ -76,6 +77,7 @@ declare module "@mindline/sync" {
76
77
  scopes: string[];
77
78
  authTS: Date;
78
79
  sel: boolean; // selection state
80
+ loggingIn: boolean;
79
81
  constructor();
80
82
  }
81
83
  // tenant (Azure AD tenant, AD domain, Google workspace)
@@ -103,6 +105,7 @@ declare module "@mindline/sync" {
103
105
  workspaceIDs: string;
104
106
  sel: boolean; // selection state
105
107
  graphSP: string; // graph resource ID (service principal) for this tenant
108
+ lookupfield: string; // are we validating by TID or by domain? "Domain" | "Tenant ID"
106
109
  constructor();
107
110
  }
108
111
  // config
@@ -139,6 +142,7 @@ declare module "@mindline/sync" {
139
142
  export class Workspace {
140
143
  id: string;
141
144
  name: string;
145
+ ownerid: string;
142
146
  associatedUsers: string[];
143
147
  associatedTenants: string[];
144
148
  associatedConfigs: string[];
@@ -275,7 +279,7 @@ declare module "@mindline/sync" {
275
279
  export function signInIncrementally(user: User, scope: string): void;
276
280
  export function signOut(user: User): boolean;
277
281
  export function tenantRelationshipsGetByDomain(loggedInuser: User, tenant: Tenant, instance: IPublicClientApplication, debug: boolean): boolean;
278
- export function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, tasks: TaskArray, debug: boolean): boolean;
282
+ export function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, debug: boolean): boolean;
279
283
  export function tenantUnauthenticatedLookup(tenant: Tenant, debug: boolean): boolean;
280
284
  export function userDelegatedScopesGet(instance: IPublicClientApplication, loggedInUser: User, tenant: Tenant): { scopes: string, id: string, error: string };
281
285
  export function userDelegatedScopesRemove(instance: IPublicClientApplication, loggedInUser: User, tenant: Tenant, scope: string): boolean;
@@ -300,4 +304,5 @@ declare module "@mindline/sync" {
300
304
  export function tenantRemove(instance: IPublicClientApplication, authorizedUser: User, tenant: Tenant, workspaceId: string, debug: boolean): APIResult;
301
305
  export function userAdd(instance: IPublicClientApplication, authorizedUser: User, user: User, workspaceId: string): APIResult;
302
306
  export function userRemove(instance: IPublicClientApplication, authorizedUser: User, user: User, workspaceId: string): APIResult;
307
+ export function workspaceEdit(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult>;
303
308
  }
package/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import * as signalR from "@microsoft/signalr"
3
3
  import { IPublicClientApplication, AuthenticationResult } from "@azure/msal-browser"
4
4
  import { deserializeArray } from 'class-transformer';
5
- import { defineHeaders, adminDelete, adminPost, adminsGet, configDelete, configsGet, configPost, configPut, initPost, readerPost, tenantPut, tenantPost, tenantDelete, tenantsGet, workspacesGet } from './hybridspa';
5
+ import { defineHeaders, adminDelete, adminPost, adminsGet, configDelete, configsGet, configPost, configPut, initPost, readerPost, tenantPut, tenantPost, tenantDelete, tenantsGet, workspacePut, workspacesGet } from './hybridspa';
6
6
  import { version } from './package.json';
7
7
  import users from "./users.json";
8
8
  import tenants from "./tenants.json";
@@ -59,6 +59,9 @@ export class mindlineConfig {
59
59
  return `https://${mindlineConfig.environmentTag}-configurationapi-westus.azurewebsites.net/api/v1/tenants`;
60
60
  };
61
61
  static workspaceEndpoint(): string {
62
+ return `https://${mindlineConfig.environmentTag}-configurationapi-westus.azurewebsites.net/api/v1/workspace`;
63
+ };
64
+ static workspacesEndpoint(): string {
62
65
  return `https://${mindlineConfig.environmentTag}-configurationapi-westus.azurewebsites.net/api/v1/workspaces`;
63
66
  };
64
67
  // SignalR endpoint
@@ -118,6 +121,7 @@ export class User {
118
121
  scopes: string[]; // to detect if incremental consent has happened
119
122
  authTS: Date; // timestamp user was authenticated
120
123
  sel: boolean; // selection state
124
+ loggingIn: boolean; // set when the user is logging in to support spinner visibility
121
125
  constructor() {
122
126
  this.oid = "";
123
127
  this.name = "";
@@ -134,6 +138,7 @@ export class User {
134
138
  this.scopes = new Array();
135
139
  this.authTS = new Date(0);
136
140
  this.sel = false;
141
+ this.loggingIn = false;
137
142
  }
138
143
  }
139
144
  export enum TenantType {
@@ -160,6 +165,7 @@ export class Tenant {
160
165
  workspaceIDs: string;
161
166
  sel: boolean; // selection state
162
167
  graphSP: string; // graph resource ID (service principal) for this tenant
168
+ lookupfield: string; // are we validating by TID or by domain? "Domain" | "Tenant ID"
163
169
  constructor() {
164
170
  this.tid = "";
165
171
  this.name = "";
@@ -171,6 +177,7 @@ export class Tenant {
171
177
  this.workspaceIDs = "";
172
178
  this.sel = false;
173
179
  this.graphSP = "";
180
+ this.lookupfield = "Domain";
174
181
  }
175
182
  }
176
183
  function getAppId(authority: string): string {
@@ -249,6 +256,7 @@ export class Config {
249
256
  export class Workspace {
250
257
  id: string;
251
258
  name: string;
259
+ ownerid: string;
252
260
  associatedUsers: string[];
253
261
  associatedTenants: string[];
254
262
  associatedConfigs: string[];
@@ -409,6 +417,7 @@ export class InitInfo {
409
417
  newuser.scopes = user.scopes;
410
418
  newuser.authTS = new Date(user.authTS);
411
419
  newuser.sel = user.sel;
420
+ newuser.loggingIn = user.loggingIn;
412
421
  return newuser
413
422
  });
414
423
  }
@@ -427,6 +436,7 @@ export class InitInfo {
427
436
  newtenant.authority = tenant.authority;
428
437
  newtenant.workspaceIDs = tenant.workspaceIDs;
429
438
  newtenant.sel = tenant.sel;
439
+ newtenant.lookupfield = tenant.lookupfield;
430
440
  return newtenant;
431
441
  });
432
442
  }
@@ -455,6 +465,7 @@ export class InitInfo {
455
465
  let newworkspace: Workspace = new Workspace();
456
466
  newworkspace.id = workspace.id;
457
467
  newworkspace.name = workspace.name;
468
+ newworkspace.ownerid = workspace.ownerid;
458
469
  newworkspace.associatedUsers = workspace.associatedUsers;
459
470
  newworkspace.associatedTenants = workspace.associatedTenants;
460
471
  newworkspace.associatedConfigs = workspace.associatedConfigs;
@@ -1508,7 +1519,7 @@ export async function tenantRelationshipsGetByDomain(loggedInUser: User, tenant:
1508
1519
  return false; // failed, no need for UX to re-render
1509
1520
  }
1510
1521
  //tenantRelationshipsGetById - query AAD for associated company name and domain
1511
- export async function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, tasks: TaskArray, debug: boolean): Promise<boolean> {
1522
+ export async function tenantRelationshipsGetById(user: User, ii: InitInfo, instance: IPublicClientApplication, debug: boolean): Promise<boolean> {
1512
1523
  console.log("**** tenantRelationshipsGetById");
1513
1524
  if (debug) debugger;
1514
1525
  // since we should mainly be called when a user has newly logged in, we can afford the performance hit of looking up the tenant name and domain again
@@ -1537,8 +1548,6 @@ export async function tenantRelationshipsGetById(user: User, ii: InitInfo, insta
1537
1548
  tenantEndpoint += "(tenantId='";
1538
1549
  tenantEndpoint += user.tid;
1539
1550
  tenantEndpoint += "')";
1540
- // track time of tenant details query
1541
- tasks.setTaskStart("GET tenant details", new Date());
1542
1551
  console.log("tenantRelationshipsGetById: Attempting GET from /findTenantInformationByTenantId:", tenantEndpoint);
1543
1552
  let response = await fetch(tenantEndpoint, options);
1544
1553
  let data = await response.json();
@@ -1557,7 +1566,6 @@ export async function tenantRelationshipsGetById(user: User, ii: InitInfo, insta
1557
1566
  debugger;
1558
1567
  }
1559
1568
  console.log("tenantRelationshipsGetById: Successful GET from /findTenantInformationByTenantId: ", data.displayName);
1560
- tasks.setTaskEnd("GET tenant details", new Date(), "complete");
1561
1569
  return true; // success, need UX to re-render
1562
1570
  }
1563
1571
  else {
@@ -1566,20 +1574,13 @@ export async function tenantRelationshipsGetById(user: User, ii: InitInfo, insta
1566
1574
  }
1567
1575
  catch (error: any) {
1568
1576
  console.log("tenantRelationshipsGetById: Failed to GET from /findTenantInformationByTenantId: ", error);
1569
- tasks.setTaskEnd("GET tenant details", new Date(), "failed");
1570
1577
  return false; // failed, no need for UX to re-render
1571
1578
  }
1572
- tasks.setTaskEnd("GET tenant details", new Date(), "failed");
1573
1579
  return false; // failed, no need for UX to re-render
1574
1580
  }
1575
1581
  //tenantUnauthenticatedLookup (from https://gettenantpartitionweb.azurewebsites.net/js/gettenantpartition.js)
1576
1582
  export async function tenantUnauthenticatedLookup(tenant: Tenant, debug: boolean): Promise<boolean> {
1577
1583
  if (debug) debugger;
1578
- // since we should mainly be called when a user is performing a lookup, we can afford the performance hit of looking up the tenant name and domain again
1579
- // do we already have a valid tenant ID? if so, nothing to add
1580
- //if (tenant.tid !== "") return false;
1581
- // do we not have a valid domain? if so, nothing to lookup
1582
- if (tenant.domain == "") return false;
1583
1584
  // prepare the 3 endpoints and corresponding regular expressions
1584
1585
  let endpoints: string[] = [graphConfig.authorityWW, graphConfig.authorityUS, graphConfig.authorityCN];
1585
1586
  let regexes: RegExp[] = [graphConfig.authorityWWRegex, graphConfig.authorityUSRegex, graphConfig.authorityCNRegex];
@@ -1589,7 +1590,12 @@ export async function tenantUnauthenticatedLookup(tenant: Tenant, debug: boolean
1589
1590
  for (let j = 0; j < 3; j++) {
1590
1591
  // create well-known openid endpoint
1591
1592
  var openidEndpoint = endpoints[j];
1592
- openidEndpoint += tenant.domain;
1593
+ if (tenant.lookupfield == "Domain") {
1594
+ openidEndpoint += tenant.domain;
1595
+ }
1596
+ else if (tenant.lookupfield == "Tenant ID") {
1597
+ openidEndpoint += tenant.tid;
1598
+ }
1593
1599
  openidEndpoint += "/.well-known/openid-configuration";
1594
1600
  console.log("Attempting GET from openid well-known endpoint: ", openidEndpoint);
1595
1601
  response = await fetch(openidEndpoint);
@@ -1778,7 +1784,6 @@ export async function configsRefresh(instance: IPublicClientApplication, authori
1778
1784
  result.status = 500;
1779
1785
  return result;
1780
1786
  }
1781
- // retrieve Workspace(s), User(s), Tenant(s), Config(s) given newly logged in user
1782
1787
  export async function initGet(instance: IPublicClientApplication, authorizedUser: User, user: User, ii: InitInfo, tasks: TaskArray, debug: boolean): Promise<APIResult> {
1783
1788
  console.log(`>>>>>> initGet`);
1784
1789
  let result: APIResult = new APIResult();
@@ -1794,7 +1799,9 @@ export async function initGet(instance: IPublicClientApplication, authorizedUser
1794
1799
  let loggedInUser: User | undefined = ii.us.find((u: User) => (u.session === "Sign Out" && u.authority === user.authority));
1795
1800
  if (loggedInUser != null) {
1796
1801
  // get tenant name and domain from AAD to pass to Configuration API
1797
- result.result = await tenantRelationshipsGetById(user, ii, instance, tasks, debug);
1802
+ tasks.setTaskStart("GET tenant details", new Date());
1803
+ result.result = await tenantRelationshipsGetById(user, ii, instance, debug);
1804
+ tasks.setTaskEnd("GET tenant details", new Date(), "complete");
1798
1805
  // if this is the first time, we have just gotten tenant info, then we must POST user and not-yet-onboarded tenant to back end
1799
1806
  if (result.result) {
1800
1807
  tasks.setTaskStart("POST config init", new Date());
@@ -1837,7 +1844,11 @@ export async function userAdd(instance: IPublicClientApplication, authorizedUser
1837
1844
  export async function userRemove(instance: IPublicClientApplication, authorizedUser: User, user: User, workspaceId: string): Promise<APIResult> {
1838
1845
  return adminDelete(instance, authorizedUser, user, workspaceId);
1839
1846
  }
1840
- // Mindline Config API internal helper functions
1847
+ export async function workspaceEdit(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult>
1848
+ {
1849
+ return await workspacePut(instance, authorizedUser, workspaceId, workspaceName);
1850
+ }
1851
+ // retrieve Workspace(s), User(s), Tenant(s), Config(s) given newly logged in user
1841
1852
  function processReturnedAdmins(workspace: Workspace, ii: InitInfo, returnedAdmins: Array<Object>) {
1842
1853
  returnedAdmins.map((item) => {
1843
1854
  // are we already tracking this user?
@@ -2020,6 +2031,7 @@ async function workspaceInfoGet(instance: IPublicClientApplication, authorizedUs
2020
2031
  // set id and name based on returned data
2021
2032
  workspace.id = o.id;
2022
2033
  workspace.name = o.name;
2034
+ workspace.ownerid = o.workspaceOwnerUserId;
2023
2035
  // parallel GET admins, tenants, configs associated with this workspace
2024
2036
  let adminsPromise: Promise<APIResult> = adminsGet(instance, authorizedUser, workspace.id, debug);
2025
2037
  let tenantsPromise: Promise<APIResult> = tenantsGet(instance, authorizedUser, workspace.id, debug);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mindline/sync",
3
3
  "type": "module",
4
- "version": "1.0.66",
4
+ "version": "1.0.68",
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.",