@mindline/sync 1.0.87 → 1.0.89

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/index.ts CHANGED
@@ -14,6 +14,7 @@ import syncmilestones from './syncmilestones';
14
14
  import resources from './resources';
15
15
  import actors from './actors';
16
16
  import { log } from "console";
17
+
17
18
  const FILTER_FIELD = "workspaceIDs";
18
19
  // called by unit tests
19
20
  export function sum(a: number, b: number): number {
@@ -2491,4 +2492,1012 @@ async function readResources(instance: IPublicClientApplication, user: User): Pr
2491
2492
  return false;
2492
2493
  }
2493
2494
  return true;
2495
+ }
2496
+
2497
+ //hybridspa.ts - calls to Mindline Config API
2498
+
2499
+ // helper functions
2500
+ function getAPIScope(user: User): string {
2501
+ let apiAppID: string = "8d95d21c-c378-4bb0-9f52-88c30d271e7a";
2502
+ let authority: string = user.authority.toLowerCase();
2503
+ if (authority.startsWith("https://login.microsoftonline.com/"))
2504
+ apiAppID = "8d95d21c-c378-4bb0-9f52-88c30d271e7a";
2505
+ else if (authority.startsWith("https://login.microsoftonline.us/"))
2506
+ apiAppID = "48da942e-ea3d-49e4-a054-81649012f8f2";
2507
+ else if (authority.startsWith("https://login.partner.microsoftonline.cn/"))
2508
+ apiAppID = "c91d32e4-dcc5-4d77-826a-16e93ffce666";
2509
+ let apiScope: string = `api://${apiAppID}/Config.Write`;
2510
+ return apiScope;
2511
+ }
2512
+ // TODO: this is where you want to trigger a re-authentication if token expires
2513
+ async function mindlineDefineHeaders(
2514
+ instance: IPublicClientApplication,
2515
+ user: User
2516
+ ): Promise<Headers> {
2517
+ debugger;
2518
+ const headers = new Headers();
2519
+ headers.append("Content-Type", "application/json");
2520
+ headers.append("accept", "*/*");
2521
+ // always call acquireTokenSilent, handling expired tokens on exception
2522
+ const apiScope: string = getAPIScope(user);
2523
+ try {
2524
+ let accounts: AccountInfo[] = instance.getAllAccounts();
2525
+ let homeAccountId = user.oid + "." + user.tid;
2526
+ let account: AccountInfo = null;
2527
+ for (let i: number = 0; i < accounts.length; i++) {
2528
+ if (accounts[i].homeAccountId == homeAccountId) {
2529
+ account = accounts[i];
2530
+ }
2531
+ }
2532
+ let response: AuthenticationResult = await instance.acquireTokenSilent({
2533
+ scopes: [apiScope],
2534
+ account: account
2535
+ });
2536
+ user.mindlineAccessToken = response.accessToken; // cache access token
2537
+ console.log("Front end mindline token acquired silently: " + user.mindlineAccessToken.slice(0, 20));
2538
+ }
2539
+ catch (error: any) {
2540
+ try {
2541
+ console.log("Front end mindline token silent acquisition failure, triggering redirect: " + error);
2542
+ // fallback to redirect if silent acquisition fails
2543
+ let accounts: AccountInfo[] = instance.getAllAccounts();
2544
+ let homeAccountId = user.oid + "." + user.tid;
2545
+ let account: AccountInfo = null;
2546
+ for (let i: number = 0; i < accounts.length; i++) {
2547
+ if (accounts[i].homeAccountId == homeAccountId) {
2548
+ account = accounts[i];
2549
+ }
2550
+ }
2551
+ // assumption: this redirect will trigger login flow callbacks in program.cs
2552
+ instance.acquireTokenRedirect({
2553
+ scopes: [apiScope],
2554
+ account: account
2555
+ });
2556
+ }
2557
+ catch (error: any) {
2558
+ console.log("Front end mindline token redirect acquisition failure: " + error);
2559
+ }
2560
+ }
2561
+ headers.append("Authorization", `Bearer ${user.mindlineAccessToken}`);
2562
+ return headers;
2563
+ }
2564
+ export async function processErrors(response: Response): Promise<string> {
2565
+ let errorString: string = "";
2566
+ if (response.status === 401) {
2567
+ errorString = response.statusText;
2568
+ if (errorString != "") return errorString;
2569
+ }
2570
+ let data = await response.json();
2571
+ // process errors from Mindline Config API
2572
+ if (data.error !== undefined) {
2573
+ errorString = `Error: ${data.error} Message: ${data.message}`;
2574
+ } else if (data.errors !== undefined) {
2575
+ let errorArray = Object.keys(data.errors);
2576
+ let errorlist: string = "";
2577
+ errorString = errorArray.reduce(
2578
+ (acc, curr) => acc + curr + ": " + data.errors[curr] + " ",
2579
+ errorlist
2580
+ );
2581
+ } else if (data.title !== undefined) {
2582
+ errorString = data.title;
2583
+ } else {
2584
+ debugger;
2585
+ }
2586
+ return errorString;
2587
+ }
2588
+ //adminDelete
2589
+ export async function adminDelete(
2590
+ instance: IPublicClientApplication,
2591
+ authorizedUser: User,
2592
+ user: User,
2593
+ workspaceId: string
2594
+ ): Promise<APIResult> {
2595
+ let result: APIResult = new APIResult();
2596
+ // we need either oid or mail for the user and valid workspace id
2597
+ if ((user.oid == "" && user.mail == "") || workspaceId == "") {
2598
+ result.result = false;
2599
+ result.error = "adminDelete: invalid parameters";
2600
+ result.status = 500;
2601
+ return result;
2602
+ }
2603
+ // define admin endpoint and add workspaceId parameter
2604
+ let url: URL | null = null;
2605
+ url = new URL(mindlineConfig.adminEndpoint());
2606
+ url.searchParams.append("workspaceId", workspaceId);
2607
+ url.searchParams.append("email", user.mail);
2608
+ // create headers
2609
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2610
+ // make endpoint call
2611
+ let options = { method: "DELETE", headers: headers };
2612
+ try {
2613
+ console.log("Attempting DELETE from /admin: " + url!.href);
2614
+ let response = await fetch(url!.href, options);
2615
+ if (response.status === 200 && response.statusText === "OK") {
2616
+ console.log(`Successful DELETE from /admin: ${url!.href}`);
2617
+ return result;
2618
+ } else {
2619
+ result.error = await processErrors(response);
2620
+ console.log(`Failed DELETE from /admin: ${url.href}`);
2621
+ console.log(result.error);
2622
+ result.status = 500;
2623
+ result.result = false;
2624
+ return result;
2625
+ }
2626
+ } catch (error: any) {
2627
+ result.error = error.message;
2628
+ result.status = 500;
2629
+ result.result = false;
2630
+ console.log(error.message);
2631
+ }
2632
+ return result;
2633
+ }
2634
+ //adminsGet
2635
+ export async function adminsGet(
2636
+ instance: IPublicClientApplication,
2637
+ user: User,
2638
+ workspaceID: string,
2639
+ debug: boolean
2640
+ ): Promise<APIResult> {
2641
+ let result: APIResult = new APIResult();
2642
+ // we need a workspace id
2643
+ if (workspaceID === "") {
2644
+ result.result = false;
2645
+ result.status = 500;
2646
+ result.error = "adminsGet: no workspace provided";
2647
+ return result;
2648
+ }
2649
+ // create endpoint
2650
+ let endpoint: string = mindlineConfig.adminsEndpoint();
2651
+ // add parameter to endpoint
2652
+ let url: URL = new URL(endpoint);
2653
+ url.searchParams.append("workspaceId", workspaceID);
2654
+ // create headers
2655
+ const headers = await mindlineDefineHeaders(instance, user);
2656
+ // make endpoint call
2657
+ let options = { method: "GET", headers: headers };
2658
+ try {
2659
+ if (debug) debugger;
2660
+ console.log("Attempting GET from /admins: " + url.href);
2661
+ let response = await fetch(url.href, options);
2662
+ if (response.status === 200 && response.statusText === "OK") {
2663
+ let returnedArray: Array<Object> = await response.json();
2664
+ if (returnedArray != null) {
2665
+ result.array = returnedArray;
2666
+ let initialValue: string = "";
2667
+ console.log(`Successful GET from /admins: ${result.array.reduce((acc, curr) => acc + curr.email + " ", initialValue)}`);
2668
+ return result;
2669
+ }
2670
+ else {
2671
+ result.error = `Failed GET from /admins: failed to JSON-parse response`;
2672
+ console.log(result.error);
2673
+ result.status = 500;
2674
+ result.result = false;
2675
+ return result;
2676
+ }
2677
+ }
2678
+ else {
2679
+ console.log(`Failed GET from /admins: ${url.href}`);
2680
+ result.error = await processErrors(response);
2681
+ result.status = 500;
2682
+ result.result = false;
2683
+ console.log(result.error);
2684
+ return result;
2685
+ }
2686
+ }
2687
+ catch (error: any) {
2688
+ result.error = error.message;
2689
+ result.status = 500;
2690
+ result.result = false;
2691
+ console.log(error.message);
2692
+ }
2693
+ return result;
2694
+ }
2695
+ //adminPost: write validated admin to back end
2696
+ export async function adminPost(
2697
+ instance: IPublicClientApplication,
2698
+ authorizedUser: User,
2699
+ user: User,
2700
+ workspaceId: string
2701
+ ): Promise<APIResult> {
2702
+ let result: APIResult = new APIResult();
2703
+ if (user.mail == "" || user.authority == "" || user.tid === "") {
2704
+ result.result = false;
2705
+ result.error = "adminPost: invalid argument";
2706
+ result.status = 500;
2707
+ return result;
2708
+ }
2709
+ // create admin endpoint
2710
+ let endpoint: string = mindlineConfig.adminEndpoint();
2711
+ // create headers
2712
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2713
+ // create admin body
2714
+ let adminBody: string = `
2715
+ {"email": "${user.mail}",
2716
+ "tenantId": "${user.tid}",
2717
+ "workspaceId": "${workspaceId}"
2718
+ }`;
2719
+ let options = { method: "POST", headers: headers, body: adminBody };
2720
+ // make admin endpoint call
2721
+ try {
2722
+ console.log("Attempting POST to /admin: " + endpoint);
2723
+ let response = await fetch(endpoint, options);
2724
+ if (response.status === 200 && response.statusText === "OK") {
2725
+ console.log(`Successful POST to /admin: ${adminBody}`);
2726
+ return result;
2727
+ } else {
2728
+ result.error = await processErrors(response);
2729
+ console.log(`Failed POST to /admin: ${adminBody}`);
2730
+ console.log(result.error);
2731
+ result.status = 500;
2732
+ result.result = false;
2733
+ return result;
2734
+ }
2735
+ } catch (error: any) {
2736
+ result.error = error.message;
2737
+ result.status = 500;
2738
+ result.result = false;
2739
+ console.log(error.message);
2740
+ }
2741
+ return result;
2742
+ }
2743
+ //configConsentReadPut
2744
+ export async function configConsentReadPut(instance: IPublicClientApplication, authorizedUser: User, configId: string, tid: string, consent: boolean): Promise<APIResult> {
2745
+ let result: APIResult = new APIResult();
2746
+ // create parameterized config consent endpoint
2747
+ let endpoint: string = mindlineConfig.configConsentEndpoint();
2748
+ let url: URL = new URL(endpoint);
2749
+ url.searchParams.append("configurationId", configId);
2750
+ // create headers
2751
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2752
+ // create body
2753
+ let configConsentReadBody: string = `
2754
+ {
2755
+ "tenantId": "${tid}",
2756
+ "isReadPermissionConsented": ${consent ? "true" : "false"}
2757
+ }`;
2758
+ // make endpoint call
2759
+ let options = { method: "PUT", headers: headers, body: configConsentReadBody };
2760
+ try {
2761
+ console.log("Attempting PUT read consent to /configuration/consent: " + url.href);
2762
+ let response = await fetch(url.href, options);
2763
+ if (response.status === 200 && response.statusText === "OK") {
2764
+ console.log(`Successful PUT to ${url.href}`);
2765
+ return result;
2766
+ }
2767
+ else {
2768
+ result.error = await processErrors(response);
2769
+ console.log(`Failed PUT to ${url.href}`);
2770
+ console.log(result.error);
2771
+ result.status = 500;
2772
+ result.result = false;
2773
+ return result;
2774
+ }
2775
+ }
2776
+ catch (error: any) {
2777
+ result.error = error.message;
2778
+ result.status = 500;
2779
+ result.result = false;
2780
+ console.log(error.message);
2781
+ }
2782
+ return result;
2783
+ }
2784
+ //configConsentWritePut
2785
+ export async function configConsentWritePut(instance: IPublicClientApplication, authorizedUser: User, configId: string, tid: string, consent: boolean): Promise<APIResult> {
2786
+ let result: APIResult = new APIResult();
2787
+ // create parameterized config consent endpoint
2788
+ let endpoint: string = mindlineConfig.configConsentEndpoint();
2789
+ let url: URL = new URL(endpoint);
2790
+ url.searchParams.append("configurationId", configId);
2791
+ // create headers
2792
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2793
+ // create body
2794
+ let configConsentWriteBody: string = `
2795
+ {
2796
+ "tenantId": "${tid}",
2797
+ "isWritePermissionConsented": ${consent ? "true" : "false"}
2798
+ }`;
2799
+ // make endpoint call
2800
+ let options = { method: "PUT", headers: headers, body: configConsentWriteBody };
2801
+ try {
2802
+ console.log("Attempting PUT read consent to /configuration/consent: " + url.href);
2803
+ let response = await fetch(url.href, options);
2804
+ if (response.status === 200 && response.statusText === "OK") {
2805
+ console.log(`Successful PUT to ${url.href}`);
2806
+ return result;
2807
+ }
2808
+ else {
2809
+ result.error = await processErrors(response);
2810
+ console.log(`Failed PUT to ${url.href}`);
2811
+ console.log(result.error);
2812
+ result.status = 500;
2813
+ result.result = false;
2814
+ return result;
2815
+ }
2816
+ }
2817
+ catch (error: any) {
2818
+ result.error = error.message;
2819
+ result.status = 500;
2820
+ result.result = false;
2821
+ console.log(error.message);
2822
+ }
2823
+ return result;
2824
+ }
2825
+ //configDelete
2826
+ export async function configDelete(
2827
+ instance: IPublicClientApplication,
2828
+ authorizedUser: User,
2829
+ config: Config,
2830
+ workspaceId: string,
2831
+ debug: boolean
2832
+ ): Promise<APIResult> {
2833
+ let result: APIResult = new APIResult();
2834
+ if (config.id === "" || workspaceId == "") {
2835
+ result.result = false;
2836
+ result.error = "configPost: invalid config ID";
2837
+ result.status = 500;
2838
+ return result;
2839
+ }
2840
+ let url: URL | null = null;
2841
+ url = new URL(mindlineConfig.configEndpoint());
2842
+ url.searchParams.append("configurationId", config.id);
2843
+ // create headers
2844
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2845
+ // make endpoint call
2846
+ let options = { method: "DELETE", headers: headers };
2847
+ try {
2848
+ console.log("Attempting DELETE from /config: " + url.href);
2849
+ let response = await fetch(url.href, options);
2850
+ if (response.status === 200 && response.statusText === "OK") {
2851
+ console.log(`Successful DELETE from /config`);
2852
+ return result;
2853
+ }
2854
+ else {
2855
+ result.error = await processErrors(response);
2856
+ console.log(`Failed DELETE from ${url.href}`);
2857
+ console.log(result.error);
2858
+ result.status = 500;
2859
+ result.result = false;
2860
+ return result;
2861
+ }
2862
+ }
2863
+ catch (error: any) {
2864
+ result.error = error.message;
2865
+ result.status = 500;
2866
+ result.result = false;
2867
+ console.log(error.message);
2868
+ }
2869
+ return result;
2870
+ }
2871
+ //configPatch
2872
+ export async function configPatch(
2873
+ instance: IPublicClientApplication,
2874
+ authorizedUser: User,
2875
+ configurationId: string,
2876
+ enabled: boolean,
2877
+ debug: boolean
2878
+ ): Promise<APIResult> {
2879
+ let result: APIResult = new APIResult();
2880
+ if (configurationId === "") {
2881
+ result.result = false;
2882
+ result.error = "configPatch: invalid config ID";
2883
+ result.status = 500;
2884
+ return result;
2885
+ }
2886
+ // create parametrized config endpoint
2887
+ let endpoint: string = mindlineConfig.configEnabledEndpoint();
2888
+ let url: URL = new URL(endpoint);
2889
+ url.searchParams.append("configurationId", configurationId);
2890
+ url.searchParams.append("isEnabled", enabled.toString());
2891
+ // create config headers
2892
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2893
+ let options = { method: "PATCH", headers: headers };
2894
+ // make config endpoint call
2895
+ try {
2896
+ if (debug) debugger;
2897
+ console.log("Attempting PATCH to /config: " + url.href);
2898
+ let response = await fetch(url.href, options);
2899
+ if (response.status === 200 && response.statusText === "OK") {
2900
+ console.log(`Successful PATCH to ${url.href}: ${enabled.toString()}`);
2901
+ return result;
2902
+ }
2903
+ else {
2904
+ result.error = await processErrors(response);
2905
+ console.log(`Failed PATCH to ${url.href}: ${enabled.toString()}`);
2906
+ console.log(result.error);
2907
+ result.status = 500;
2908
+ result.result = false;
2909
+ return result;
2910
+ }
2911
+ }
2912
+ catch (error: any) {
2913
+ result.error = error.message;
2914
+ result.status = 500;
2915
+ result.result = false;
2916
+ console.log(error.message);
2917
+ }
2918
+ return result;
2919
+ }
2920
+ //configPost
2921
+ export async function configPost(
2922
+ instance: IPublicClientApplication,
2923
+ authorizedUser: User,
2924
+ config: Config,
2925
+ workspaceId: string,
2926
+ debug: boolean
2927
+ ): Promise<APIResult> {
2928
+ let result: APIResult = new APIResult();
2929
+ if (config.id === "") {
2930
+ result.result = false;
2931
+ result.error = "configPost: invalid config ID";
2932
+ result.status = 500;
2933
+ return result;
2934
+ }
2935
+ // create no parameter config endpoint
2936
+ let endpoint: string = mindlineConfig.configEndpoint();
2937
+ // create config headers
2938
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
2939
+ // create config body
2940
+ let configBody: string = `
2941
+ {
2942
+ "workspaceId": "${workspaceId}",
2943
+ "name": "${config.name}",
2944
+ "description": "${config.description}",
2945
+ "isEnabled": ${config.isEnabled},
2946
+ "tenants": [`;
2947
+ config.tenants.map((tci) => {
2948
+ // be sure we send null and not "null" in body
2949
+ let sourceGroupId: string = tci.sourceGroupId != "" ? `"${tci.sourceGroupId}"` : "null";
2950
+ let sourceGroupName: string = tci.sourceGroupName != "" ? `"${tci.sourceGroupName}"` : "null";
2951
+ let targetGroupId: string = tci.targetGroupId != "" ? `"${tci.targetGroupId}"` : "null";
2952
+ let targetGroupName: string = tci.targetGroupName != "" ? `"${tci.targetGroupName}"` : "null";
2953
+ // if last character is } we need a comma first
2954
+ let needComma: boolean = configBody.slice(-1) === "}";
2955
+ if (needComma) configBody += ",";
2956
+ configBody += `{
2957
+ "tenantId": "${tci.tid}",
2958
+ "sourceGroupId": ${sourceGroupId},
2959
+ "sourceGroupName": ${sourceGroupName},
2960
+ "targetGroupId": ${targetGroupId},
2961
+ "targetGroupName": ${targetGroupName},
2962
+ "configurationTenantType": "${tci.configurationTenantType}"
2963
+ }`;
2964
+ });
2965
+ configBody += `]}`;
2966
+ let options = { method: "POST", headers: headers, body: configBody };
2967
+ // make config endpoint call
2968
+ try {
2969
+ if (debug) debugger;
2970
+ console.log("Attempting POST to /config: " + endpoint);
2971
+ let response = await fetch(endpoint, options);
2972
+ if (response.status === 200 && response.statusText === "OK") {
2973
+ let data = await response.json();
2974
+ config.id = data;
2975
+ console.log(
2976
+ `Successful ConfigID: ${data} from POST to /config: ${configBody}`
2977
+ );
2978
+ return result;
2979
+ }
2980
+ else {
2981
+ result.error = await processErrors(response);
2982
+ console.log(`Failed PUT to /config: ${configBody}`);
2983
+ console.log(result.error);
2984
+ result.status = 500;
2985
+ result.result = false;
2986
+ return result;
2987
+ }
2988
+ }
2989
+ catch (error: any) {
2990
+ result.status = 500;
2991
+ result.result = false;
2992
+ result.error = error.message;
2993
+ console.log(result.error);
2994
+ return result;
2995
+ }
2996
+ }
2997
+ //configPut
2998
+ export async function configPut(
2999
+ instance: IPublicClientApplication,
3000
+ authorizedUser: User,
3001
+ config: Config,
3002
+ debug: boolean
3003
+ ): Promise<APIResult> {
3004
+ let result: APIResult = new APIResult();
3005
+ if (config.id === "") {
3006
+ result.result = false;
3007
+ result.error = "configPost: invalid config ID";
3008
+ result.status = 500;
3009
+ return result;
3010
+ }
3011
+ // create parametrized config endpoint
3012
+ let endpoint: string = mindlineConfig.configEndpoint();
3013
+ let url: URL = new URL(endpoint);
3014
+ url.searchParams.append("configurationId", config.id);
3015
+ // create config headers
3016
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
3017
+ // create config body
3018
+ let configBody: string = `
3019
+ {
3020
+ "name": "${config.name}",
3021
+ "description": "${config.description}",
3022
+ "tenants": [`;
3023
+ config.tenants.map((tci: TenantConfigInfo) => {
3024
+ // if last character is } we need a comma first
3025
+ let needComma: boolean = configBody.slice(-1) === "}";
3026
+ if (needComma) configBody += ",";
3027
+ // be sure we send null and not "null" in body
3028
+ let sourceGroupId: string = tci.sourceGroupId != "" ? `"${tci.sourceGroupId}"` : "null";
3029
+ let sourceGroupName: string = tci.sourceGroupName != "" ? `"${tci.sourceGroupName}"` : "null";
3030
+ let targetGroupId: string = tci.targetGroupId != "" ? `"${tci.targetGroupId}"` : "null";
3031
+ let targetGroupName: string = tci.targetGroupName != "" ? `"${tci.targetGroupName}"` : "null";
3032
+ configBody += `{
3033
+ "tenantId": "${tci.tid}",
3034
+ "sourceGroupId": ${sourceGroupId},
3035
+ "sourceGroupName": ${sourceGroupName},
3036
+ "targetGroupId": ${targetGroupId},
3037
+ "targetGroupName": ${targetGroupName},
3038
+ "configurationTenantType": "${tci.configurationTenantType}",
3039
+ "deltaToken": "${tci.deltaToken}"
3040
+ }`;
3041
+ });
3042
+ configBody += `]}`;
3043
+ let options = { method: "PUT", headers: headers, body: configBody };
3044
+ // make config endpoint call
3045
+ try {
3046
+ if (debug) debugger;
3047
+ console.log("Attempting PUT to /config: " + url.href);
3048
+ let response = await fetch(url.href, options);
3049
+ if (response.status === 200 && response.statusText === "OK") {
3050
+ console.log(`Successful PUT to ${url.href}: ${configBody}`);
3051
+ return result;
3052
+ }
3053
+ else {
3054
+ result.error = await processErrors(response);
3055
+ console.log(`Failed PUT to ${url.href}: ${configBody}`);
3056
+ console.log(result.error);
3057
+ result.status = 500;
3058
+ result.result = false;
3059
+ return result;
3060
+ }
3061
+ }
3062
+ catch (error: any) {
3063
+ result.error = error.message;
3064
+ result.status = 500;
3065
+ result.result = false;
3066
+ console.log(error.message);
3067
+ }
3068
+ return result;
3069
+ }
3070
+ //configsGet
3071
+ export async function configsGet(
3072
+ instance: IPublicClientApplication,
3073
+ user: User,
3074
+ workspaceID: string,
3075
+ debug: boolean
3076
+ ): Promise<APIResult> {
3077
+ let result: APIResult = new APIResult();
3078
+ // we need a workspace id
3079
+ if (workspaceID === "") {
3080
+ result.result = false;
3081
+ result.status = 500;
3082
+ result.error = "configsGet: no workspace provided";
3083
+ return result;
3084
+ }
3085
+ // create endpoint
3086
+ let endpoint: string = mindlineConfig.configsEndpoint();
3087
+ // add parameter to endpoint
3088
+ let url: URL = new URL(endpoint);
3089
+ url.searchParams.append("workspaceId", workspaceID);
3090
+ // create headers
3091
+ const headers = await mindlineDefineHeaders(instance, user);
3092
+ // make endpoint call
3093
+ let options = { method: "GET", headers: headers };
3094
+ try {
3095
+ if (debug) debugger;
3096
+ console.log("Attempting GET from /configurations: " + url.href);
3097
+ let response = await fetch(url.href, options);
3098
+ if (response.status === 200 && response.statusText === "OK") {
3099
+ let returnedArray: Array<Object> = await response.json();
3100
+ if (returnedArray != null) {
3101
+ result.array = returnedArray;
3102
+ let initialValue: string = "";
3103
+ console.log(`Successful GET from /configurations: ${result.array.reduce((acc, curr) => acc + curr.name + " ", initialValue)}`);
3104
+ return result;
3105
+ }
3106
+ else {
3107
+ result.error = `Failed GET from /configurations: failed to JSON-parse response`;
3108
+ console.log(result.error);
3109
+ result.status = 500;
3110
+ result.result = false;
3111
+ return result;
3112
+ }
3113
+ }
3114
+ else {
3115
+ console.log(`Failed GET from /configurations: ${url.href}`);
3116
+ result.error = await processErrors(response);
3117
+ result.status = 500;
3118
+ result.result = false;
3119
+ console.log(result.error);
3120
+ return result;
3121
+ }
3122
+ }
3123
+ catch (error: any) {
3124
+ result.error = error.message;
3125
+ result.status = 500;
3126
+ result.result = false;
3127
+ console.log(error.message);
3128
+ }
3129
+ return result;
3130
+ }
3131
+ //initPost
3132
+ export async function initPost(
3133
+ instance: IPublicClientApplication,
3134
+ user: User,
3135
+ debug: boolean
3136
+ ): Promise<APIResult> {
3137
+ let result: APIResult = new APIResult();
3138
+ // we expect valid company name and domain by this point
3139
+ if (user.companyName === "" || user.companyDomain === "") {
3140
+ result.result = false;
3141
+ result.error = "initPost: invalid company name or domain"
3142
+ result.status = 500;
3143
+ return result;
3144
+ }
3145
+ // create init endpoint
3146
+ let endpoint: string = mindlineConfig.initEndpoint();
3147
+ // create init headers
3148
+ const headers = await mindlineDefineHeaders(instance, user);
3149
+ // create init body
3150
+ let initBody: string = `
3151
+ {
3152
+ "tenantCreateModel": {
3153
+ "tenantId": "${user.tid}",
3154
+ "name": "${user.companyName}",
3155
+ "domain": "${user.companyDomain}",
3156
+ "type": "aad",
3157
+ "authority": "${user.authority}"
3158
+ }
3159
+ }`;
3160
+ let options = { method: "POST", headers: headers, body: initBody };
3161
+ // make init endpoint call
3162
+ try {
3163
+ if (debug) debugger;
3164
+ console.log("Attempting POST to /configuration/init: " + endpoint);
3165
+ let response = await fetch(endpoint, options);
3166
+ if (response.status === 200 && response.statusText === "OK") {
3167
+ console.log(`Successful POST to /configuration/init: ${initBody}`);
3168
+ return result;
3169
+ }
3170
+ else {
3171
+ result.error = await processErrors(response);
3172
+ result.status = 500;
3173
+ result.result = false;
3174
+ console.log(`Failed POST to /configuration/init: ${initBody}`);
3175
+ console.log(result.error);
3176
+ return result;
3177
+ }
3178
+ }
3179
+ catch (error: any) {
3180
+ result.error = error.message;
3181
+ console.log(result.error);
3182
+ }
3183
+ result.status = 500;
3184
+ result.result = false;
3185
+ return result;
3186
+ }
3187
+ //tenantDelete
3188
+ export async function tenantDelete(
3189
+ instance: IPublicClientApplication,
3190
+ authorizedUser: User,
3191
+ tenant: Tenant,
3192
+ workspaceId: string,
3193
+ debug: boolean
3194
+ ): Promise<APIResult> {
3195
+ let result: APIResult = new APIResult();
3196
+ // we expect valid tid amd workspaceId
3197
+ if (tenant.tid === "" || workspaceId === "") {
3198
+ result.result = false;
3199
+ result.error = "tenantDelete: invalid tid, workspaceId";
3200
+ result.status = 500;
3201
+ return result;
3202
+ }
3203
+ // create parametrized tenant endpoint
3204
+ let url: URL = new URL(mindlineConfig.tenantEndpoint());
3205
+ url.searchParams.append("tenantId", tenant.tid);
3206
+ url.searchParams.append("workspaceId", workspaceId);
3207
+ // create headers
3208
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
3209
+ // make tenant endpoint call
3210
+ let options = { method: "DELETE", headers: headers };
3211
+ try {
3212
+ console.log("Attempting DELETE from /tenant: " + url.href);
3213
+ let response = await fetch(url.href, options);
3214
+ if (response.status === 200 && response.statusText === "OK") {
3215
+ console.log(`Successful DELETE from /tenant: ${url.href}`);
3216
+ return result;
3217
+ }
3218
+ else {
3219
+ console.log(`Failed DELETE from /tenant: ${url.href}`);
3220
+ result.error = await processErrors(response);
3221
+ console.log(result.error);
3222
+ result.status = 500;
3223
+ result.result = false;
3224
+ return result;
3225
+ }
3226
+ }
3227
+ catch (error: any) {
3228
+ result.error = error.message;
3229
+ result.status = 500;
3230
+ result.result = false;
3231
+ console.log(result.error);
3232
+ }
3233
+ return result;
3234
+ }
3235
+ //tenantsGet
3236
+ export async function tenantsGet(
3237
+ instance: IPublicClientApplication,
3238
+ user: User,
3239
+ workspaceID: string,
3240
+ debug: boolean
3241
+ ): Promise<APIResult> {
3242
+ let result: APIResult = new APIResult();
3243
+ // we need a workspace id
3244
+ if (workspaceID === "") {
3245
+ result.result = false;
3246
+ result.status = 500;
3247
+ result.error = "tenantsGet: no workspace provided";
3248
+ return result;
3249
+ }
3250
+ // create endpoint
3251
+ let endpoint: string = mindlineConfig.tenantsEndpoint();
3252
+ // add parameter to endpoint
3253
+ let url: URL = new URL(endpoint);
3254
+ url.searchParams.append("workspaceId", workspaceID);
3255
+ // create headers
3256
+ const headers = await mindlineDefineHeaders(instance, user);
3257
+ // make endpoint call
3258
+ let options = { method: "GET", headers: headers };
3259
+ try {
3260
+ if (debug) debugger;
3261
+ console.log(`Attempting GET from /tenants: ${url.href}`);
3262
+ let response = await fetch(url.href, options);
3263
+ if (response.status === 200 && response.statusText === "OK") {
3264
+ let returnedArray: Array<Object> = await response.json();
3265
+ if (returnedArray != null) {
3266
+ result.array = returnedArray;
3267
+ let initialValue: string = "";
3268
+ console.log(`Successful GET from /tenants: ${result.array.reduce((acc, curr) => acc + curr.domain + " ", initialValue)}`);
3269
+ return result;
3270
+ }
3271
+ else {
3272
+ result.error = `Failed GET from /tenants: failed to JSON-parse response`;
3273
+ console.log(result.error);
3274
+ result.status = 500;
3275
+ result.result = false;
3276
+ return result;
3277
+ }
3278
+ }
3279
+ else {
3280
+ console.log(`Failed GET from /tenants: ${url.href}`);
3281
+ result.error = await processErrors(response);
3282
+ result.status = 500;
3283
+ result.result = false;
3284
+ console.log(result.error);
3285
+ return result;
3286
+ }
3287
+ }
3288
+ catch (error: any) {
3289
+ result.error = error.message;
3290
+ result.status = 500;
3291
+ result.result = false;
3292
+ console.log(error.message);
3293
+ }
3294
+ return result;
3295
+ }
3296
+ //tenantPost: write validated tenant to back end
3297
+ export async function tenantPost(
3298
+ instance: IPublicClientApplication,
3299
+ addingUser: User,
3300
+ tenant: Tenant,
3301
+ workspaceId: string
3302
+ ): Promise<APIResult> {
3303
+ let result: APIResult = new APIResult();
3304
+ // we expect valid tid, name, validated domain
3305
+ if (tenant.tid === "" || tenant.name === "" || tenant.domain === "") {
3306
+ result.result = false;
3307
+ result.error = "tenantPost: invalid tid, name, domain";
3308
+ result.status = 500;
3309
+ return result;
3310
+ }
3311
+ // create parametrized tenant endpoint
3312
+ let endpoint: string = mindlineConfig.tenantEndpoint();
3313
+ let url: URL = new URL(endpoint);
3314
+ url.searchParams.append("workspaceId", workspaceId);
3315
+ // create tenant headers
3316
+ const headers = await mindlineDefineHeaders(instance, addingUser);
3317
+ // create tenant body
3318
+ let tenantBody: string = `
3319
+ {"tenantId": "${tenant.tid}",
3320
+ "name": "${tenant.name}",
3321
+ "domain": "${tenant.domain}",
3322
+ "type": 1,
3323
+ "authority": "${tenant.authority}"
3324
+ }`;
3325
+ let options = { method: "POST", headers: headers, body: tenantBody };
3326
+ // make tenant endpoint call
3327
+ try {
3328
+ console.log(`Attempting POST to ${url.href}: ${tenantBody}`);
3329
+ let response = await fetch(url.href, options);
3330
+ if (response.status === 200 && response.statusText === "OK") {
3331
+ console.log(`Successful POST to ${url.href}: ${tenantBody}`);
3332
+ return result;
3333
+ }
3334
+ else {
3335
+ console.log(`Failed POST to ${url.href}: ${tenantBody}`);
3336
+ result.error = await processErrors(response);
3337
+ console.log(result.error);
3338
+ result.status = 500;
3339
+ result.result = false;
3340
+ return result;
3341
+ }
3342
+ }
3343
+ catch (error: any) {
3344
+ result.error = error.message;
3345
+ result.status = 500;
3346
+ result.result = false;
3347
+ console.log(result.error);
3348
+ }
3349
+ return result;
3350
+ }
3351
+ //workspacePut
3352
+ export async function workspacePut(instance: IPublicClientApplication, authorizedUser: User, workspaceId: string, workspaceName: string): Promise<APIResult> {
3353
+ let result: APIResult = new APIResult();
3354
+ if (workspaceId == "" || workspaceName == "") {
3355
+ result.result = false;
3356
+ result.error = "workspacePut: invalid workspace ID or name";
3357
+ result.status = 500;
3358
+ return result;
3359
+ }
3360
+ // create parameterized workspace endpoint
3361
+ let endpoint: string = mindlineConfig.workspaceEndpoint();
3362
+ let url: URL = new URL(endpoint);
3363
+ url.searchParams.append("workspaceId", workspaceId);
3364
+ url.searchParams.append("workspaceName", workspaceName);
3365
+ // create workspace headers
3366
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
3367
+ let options = { method: "PUT", headers: headers };
3368
+ // make config endpoint call
3369
+ try {
3370
+ console.log("Attempting PUT to /workspace: " + url.href);
3371
+ let response = await fetch(url.href, options);
3372
+ if (response.status === 200 && response.statusText === "OK") {
3373
+ console.log(`Successful PUT to ${url.href}`);
3374
+ return result;
3375
+ }
3376
+ else {
3377
+ result.error = await processErrors(response);
3378
+ console.log(`Failed PUT to ${url.href}`);
3379
+ console.log(result.error);
3380
+ result.status = 500;
3381
+ result.result = false;
3382
+ return result;
3383
+ }
3384
+ }
3385
+ catch (error: any) {
3386
+ result.error = error.message;
3387
+ result.status = 500;
3388
+ result.result = false;
3389
+ console.log(error.message);
3390
+ }
3391
+ return result;
3392
+ }
3393
+ //workspacesGet
3394
+ export async function workspacesGet(
3395
+ instance: IPublicClientApplication,
3396
+ user: User,
3397
+ debug: boolean
3398
+ ): Promise<APIResult> {
3399
+ let result: APIResult = new APIResult();
3400
+ // we need a valid email address
3401
+ if (user.mail == undefined || user.mail == "") {
3402
+ result.result = false;
3403
+ result.status = 500;
3404
+ result.error = "adminsGet: no workspace provided";
3405
+ return result;
3406
+ }
3407
+ // create workspaces endpoint
3408
+ let endpoint: string = mindlineConfig.workspacesEndpoint();
3409
+ // create workspace endpoint
3410
+ let url: URL = new URL(endpoint);
3411
+ // create workspace headers
3412
+ const headers = await mindlineDefineHeaders(instance, user);
3413
+ // make workspace endpoint call
3414
+ let options = { method: "GET", headers: headers };
3415
+ try {
3416
+ if (debug) debugger;
3417
+ console.log("Attempting GET from /workspaces endpoint: " + url.href);
3418
+ let response = await fetch(url.href, options);
3419
+ if (response.status === 200 && response.statusText === "OK") {
3420
+ let returnedArray: Array<Object> = await response.json();
3421
+ if (returnedArray != null) {
3422
+ result.array = returnedArray;
3423
+ let initialValue: string = "";
3424
+ console.log(`Successful GET from /workspaces: ${result.array.reduce((acc, curr) => acc + curr.name + " ", initialValue)}`);
3425
+ return result;
3426
+ }
3427
+ else {
3428
+ result.error = `Failed GET from /workspaces: failed to JSON-parse response`;
3429
+ console.log(result.error);
3430
+ result.status = 500;
3431
+ result.result = false;
3432
+ return result;
3433
+ }
3434
+ }
3435
+ else {
3436
+ console.log(`Failed GET from /workspaces: ${url.href}`);
3437
+ result.error = await processErrors(response);
3438
+ result.status = 500;
3439
+ result.result = false;
3440
+ console.log(result.error);
3441
+ return result;
3442
+ }
3443
+ }
3444
+ catch (error: any) {
3445
+ result.error = error.message;
3446
+ result.status = 500;
3447
+ result.result = false;
3448
+ console.log(error.message);
3449
+ }
3450
+ return result;
3451
+ }
3452
+ //readerPost
3453
+ export async function readerPost(
3454
+ instance: IPublicClientApplication,
3455
+ authorizedUser: User,
3456
+ config: Config
3457
+ ): Promise<APIResult> {
3458
+ let result: APIResult = new APIResult();
3459
+ if (instance == null || authorizedUser == null) {
3460
+ result.result = false;
3461
+ result.error = "readerPost: invalid parameters";
3462
+ result.status = 500;
3463
+ return result;
3464
+ }
3465
+ // create reader endpoint
3466
+ let readerEndpoint: string = mindlineConfig.readerStartSyncEndpoint();
3467
+ let url: URL = new URL(readerEndpoint);
3468
+ url.searchParams.append("configurationId", config.id);
3469
+ // create headers
3470
+ const headers = await mindlineDefineHeaders(instance, authorizedUser);
3471
+ // make reader endpoint call
3472
+ let options = { method: "POST", headers: headers };
3473
+ try {
3474
+ console.log("Attempting POST to /startSync: " + url.href);
3475
+ let response = await fetch(url.href, options);
3476
+ if (response.status === 200 && response.statusText === "OK") {
3477
+ console.log(`Successful POST to /startSync: ${readerEndpoint}`);
3478
+ let jsonResponse = await response.json();
3479
+ if (jsonResponse.PayloadStr != "") {
3480
+ result.array = JSON.parse(jsonResponse.PayloadStr);
3481
+ }
3482
+ else {
3483
+ result.result = false;
3484
+ result.error = "readerPost: blank payload returned, sync may be disabled on back end";
3485
+ result.status = 500;
3486
+ }
3487
+ return result;
3488
+ } else {
3489
+ result.error = await processErrors(response);
3490
+ console.log(`Failed POST to /startSync: ${readerEndpoint}`);
3491
+ console.log(result.error);
3492
+ result.status = 500;
3493
+ result.result = false;
3494
+ return result;
3495
+ }
3496
+ } catch (error: any) {
3497
+ result.error = error.message;
3498
+ result.status = 500;
3499
+ result.result = false;
3500
+ console.log(error.message);
3501
+ }
3502
+ return result;
2494
3503
  }