@kwiz/common 1.0.5 → 1.0.7

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.
Files changed (59) hide show
  1. package/.madgerc +3 -0
  2. package/dist/helpers/browser.d.ts +12 -5
  3. package/dist/helpers/browser.js +9 -6
  4. package/dist/helpers/browser.js.map +1 -1
  5. package/dist/helpers/date.js +10 -5
  6. package/dist/helpers/date.js.map +1 -1
  7. package/dist/helpers/debug.js +3 -3
  8. package/dist/helpers/debug.js.map +1 -1
  9. package/dist/helpers/objects.d.ts +2 -0
  10. package/dist/helpers/objects.js +17 -2
  11. package/dist/helpers/objects.js.map +1 -1
  12. package/dist/helpers/strings.js +2 -1
  13. package/dist/helpers/strings.js.map +1 -1
  14. package/dist/types/auth.d.ts +40 -0
  15. package/dist/types/auth.js +17 -0
  16. package/dist/types/auth.js.map +1 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/index.js +1 -0
  19. package/dist/types/index.js.map +1 -1
  20. package/dist/types/libs/msal.types.d.ts +1 -15
  21. package/dist/types/libs/msal.types.js +1 -33
  22. package/dist/types/libs/msal.types.js.map +1 -1
  23. package/dist/types/rest.types.d.ts +2 -0
  24. package/dist/utils/auth/adal.d.ts +3 -0
  25. package/dist/utils/auth/adal.js +35 -0
  26. package/dist/utils/auth/adal.js.map +1 -0
  27. package/dist/utils/auth/common.d.ts +3 -0
  28. package/dist/utils/auth/common.js +16 -0
  29. package/dist/utils/auth/common.js.map +1 -0
  30. package/dist/utils/auth/discovery.d.ts +5 -0
  31. package/dist/utils/auth/discovery.js +77 -0
  32. package/dist/utils/auth/discovery.js.map +1 -0
  33. package/dist/utils/auth/index.d.ts +2 -0
  34. package/dist/utils/auth/index.js +19 -0
  35. package/dist/utils/auth/index.js.map +1 -0
  36. package/dist/utils/auth/msal.d.ts +4 -0
  37. package/dist/utils/auth/msal.js +59 -0
  38. package/dist/utils/auth/msal.js.map +1 -0
  39. package/dist/utils/axios.d.ts +6 -0
  40. package/dist/utils/axios.js +30 -0
  41. package/dist/utils/axios.js.map +1 -0
  42. package/dist/utils/index.d.ts +1 -0
  43. package/dist/utils/index.js +1 -0
  44. package/dist/utils/index.js.map +1 -1
  45. package/package.json +10 -7
  46. package/src/helpers/browser.ts +29 -11
  47. package/src/helpers/date.ts +10 -6
  48. package/src/helpers/debug.ts +4 -4
  49. package/src/helpers/objects.ts +17 -2
  50. package/src/helpers/strings.test.js +14 -2
  51. package/src/helpers/strings.ts +2 -1
  52. package/src/types/auth.ts +46 -0
  53. package/src/types/index.ts +1 -1
  54. package/src/types/libs/msal.types.ts +3 -38
  55. package/src/types/rest.types.ts +2 -0
  56. package/src/utils/auth/common.ts +9 -0
  57. package/src/utils/auth/discovery.ts +92 -0
  58. package/src/utils/auth/index.ts +3 -0
  59. package/src/utils/index.ts +1 -0
@@ -1,11 +1,14 @@
1
1
  import { makeUniqueArray } from "./collections.base";
2
2
  import { jsonParse } from "./json";
3
- import { isDate, isFunction, isNotEmptyArray, isNullOrEmptyString, isNullOrUndefined, isObject, isPrimitiveValue, primitiveTypes } from "./typecheckers";
3
+ import { isDate, isFunction, isNotEmptyArray, isNullOrEmptyString, isNullOrUndefined, isObject, isPrimitiveValue, isString, primitiveTypes } from "./typecheckers";
4
4
 
5
5
  /** global window, safe for testing and environments without a browser */
6
6
  export var $w = typeof window === "undefined" ? {
7
7
  setTimeout: setTimeout,
8
- clearTimeout: clearTimeout
8
+ clearTimeout: clearTimeout,
9
+ location: {
10
+ href: "", host: ""
11
+ }
9
12
  } as any as Window : window;
10
13
 
11
14
  /** wrapper for hasOwnProperty that satisfies https://eslint.org/docs/latest/rules/no-prototype-builtins */
@@ -253,4 +256,16 @@ class DefaultProp<T>{
253
256
  /** creates a safe property, if the value is null/undefined or empty string - it will return the default value. */
254
257
  export function GetDefaultProp<T>(defaultValue: T | (() => T), initialValue?: T, isValid?: (value: T) => boolean) {
255
258
  return new DefaultProp(defaultValue, initialValue, isValid);
259
+ }
260
+
261
+ /** Get string error message from an error object */
262
+ export function GetError(error: any, defaultError: string = "Unknown error"): string {
263
+ const err = isNullOrUndefined(error)
264
+ ? defaultError
265
+ : isString(error)
266
+ ? error
267
+ : isString((error as Error).message)
268
+ ? error.message
269
+ : defaultError;
270
+ return err.length > 0 ? err : defaultError;
256
271
  }
@@ -4,6 +4,12 @@ import { capitalizeFirstLetter, escapeXml, replaceAll, replaceRegex } from './st
4
4
 
5
5
  test('replaceAll', t => {
6
6
  assert.strictEqual(replaceAll("hello old#@! world old#@! !", "old#@!", "new!@$"), "hello new!@$ world new!@$ !");
7
+
8
+ //this failed since the input find included protected regex characters.
9
+ //escapeRegExp needs to fix that
10
+ const source = "string with special regex[:(s:) chars";
11
+ const result = "string with special regex[~~(s~~) chars";
12
+ assert.strictEqual(replaceAll(source, source, result), result);
7
13
  });
8
14
 
9
15
  test('capitalizeFirstLetter', async t => {
@@ -30,7 +36,7 @@ test('escapeXml', async t => {
30
36
 
31
37
  test('replaceRegex', t => {
32
38
  /** Match anything between {zone:*} */
33
- var matchZones = /{zone:\w+}/gi;
39
+ var match = /{zone:\w+}/gi;
34
40
 
35
41
  var source = `text {zone:one} {zone:two}
36
42
  more text
@@ -39,5 +45,11 @@ more text
39
45
  more text
40
46
  THREE`;
41
47
 
42
- assert.strictEqual(replaceRegex(source, matchZones, m => m.slice(1, m.length - 1).split(':')[1].toLocaleUpperCase()), result);
48
+ assert.strictEqual(replaceRegex(source, match, m => m.slice(1, m.length - 1).split(':')[1].toLocaleUpperCase()), result);
49
+
50
+ /** match: "](______)" */
51
+ match = /]\(.+\)/gi;
52
+ source = '[name:root](https://kwizcom.sharepoint.com/:fl:/g/contentstorage)';
53
+ result = '[name:root](https~~~~//kwizcom.sharepoint.com/~~~~fl~~~~/g/contentstorage)';
54
+ assert.strictEqual(replaceRegex(source, match, m => m.replace(/:/gi, "~~~~")), result);
43
55
  });
@@ -241,7 +241,8 @@ export function normalizeHtmlSpace(html: string) {
241
241
  }
242
242
 
243
243
  export function replaceAll(str: string, find: string, replace: string, ignoreCase = false) {
244
- return str.replace(new RegExp(find, `g${ignoreCase ? 'i' : ''}`), replace);
244
+ //must call escapeRegExp on find, to make sure it works when there are protected regex characters
245
+ return str.replace(new RegExp(escapeRegExp(find), `g${ignoreCase ? 'i' : ''}`), replace);
245
246
  }
246
247
 
247
248
  export function capitalizeFirstLetter(str: string) {
@@ -0,0 +1,46 @@
1
+ export interface ITenantInfo {
2
+ environment: AzureEnvironment;
3
+ idOrName: string;
4
+ authorityUrl: string;
5
+ valid: boolean;
6
+ }
7
+
8
+ // eslint-disable-next-line no-shadow
9
+ export const enum AzureEnvironment {
10
+ Production = 0,
11
+ PPE = 1,
12
+ China = 2,
13
+ Germany = 3,
14
+ USGovernment = 4
15
+ }
16
+ /** AuthenticationModes enum values for projects that can't use enums (when isolatedModules is true) */
17
+ export const $AzureEnvironment = {
18
+ Production: 0,
19
+ PPE: 1,
20
+ China: 2,
21
+ Germany: 3,
22
+ USGovernment: 4,
23
+ }
24
+
25
+ // eslint-disable-next-line no-shadow
26
+ export const enum AuthenticationModes {
27
+ Certificate = "certificate",
28
+ clientSecret = "secret"
29
+ }
30
+ /** AuthenticationModes enum values for projects that can't use enums (when isolatedModules is true) */
31
+ export const $AuthenticationModes = {
32
+ Certificate: AuthenticationModes.Certificate,
33
+ clientSecret: AuthenticationModes.clientSecret,
34
+ };
35
+
36
+
37
+ export type AuthContextType = {
38
+ authenticationMode: AuthenticationModes.Certificate,
39
+ clientId: string,
40
+ privateKey: string,
41
+ thumbprint: string
42
+ } | {
43
+ authenticationMode: AuthenticationModes.clientSecret,
44
+ clientId: string,
45
+ clientSecret: string
46
+ };
@@ -1,3 +1,4 @@
1
+ export * from "./auth";
1
2
  export * from "./common.types";
2
3
  export * from './flatted.types';
3
4
  export * from "./globals.types";
@@ -9,4 +10,3 @@ export * from "./regex.types";
9
10
  export * from "./rest.types";
10
11
  export * from "./sharepoint.types";
11
12
  export * from "./sharepoint.utils.types";
12
-
@@ -1,35 +1,7 @@
1
+ import { ITenantInfo } from "../auth";
2
+
1
3
  export interface IMSALBaseRequest { scopes: string[]; }
2
4
  export interface IMSALConfig { }
3
- export interface ITenantInfo {
4
- environment: AzureEnvironment;
5
- idOrName: string;
6
- authorityUrl: string;
7
- valid: boolean;
8
- }
9
-
10
- // eslint-disable-next-line no-shadow
11
- export enum AzureEnvironment {
12
- /// <summary>
13
- ///
14
- /// </summary>
15
- Production = 0,
16
- /// <summary>
17
- ///
18
- /// </summary>
19
- PPE = 1,
20
- /// <summary>
21
- ///
22
- /// </summary>
23
- China = 2,
24
- /// <summary>
25
- ///
26
- /// </summary>
27
- Germany = 3,
28
- /// <summary>
29
- ///
30
- /// </summary>
31
- USGovernment = 4
32
- }
33
5
 
34
6
  export const MSALSampleLoginPopupScript = `<p id="msg">please wait...</p>
35
7
  <script>
@@ -59,13 +31,6 @@ function finish() {
59
31
  finish();
60
32
  </script>`;
61
33
 
62
- export function GetTokenAudiencePrefix(appId: string) {
63
- return `api://${appId}`;
64
- }
65
- export function GetDefaultScope(appId: string) {
66
- return `${GetTokenAudiencePrefix(appId)}/access_as_user`;
67
- }
68
-
69
34
  export interface IMSAL {
70
35
  AutoDiscoverTenantInfo: () => Promise<ITenantInfo>;
71
36
  GetConfig: (clientId: string, authority: string, redirectUri: string) => Promise<IMSALConfig>;
@@ -76,4 +41,4 @@ declare global {
76
41
  interface IKWizComGlobalsLibs {
77
42
  msal?: IMSAL;
78
43
  }
79
- }
44
+ }
@@ -44,6 +44,8 @@ export interface IRestRequestOptions {
44
44
  [key: string]: string;
45
45
  Accept?: string;
46
46
  "content-type"?: string;
47
+ /** `Bearer ${token}` */
48
+ Authorization?: string;
47
49
  };
48
50
  /** allow cache on post requests if you provide a unique key to identify and match */
49
51
  postCacheKey?: string;
@@ -0,0 +1,9 @@
1
+ export function GetTokenAudiencePrefix(appId: string) {
2
+ return `api://${appId}`;
3
+ }
4
+ export function GetDefaultScope(appId: string) {
5
+ return `${GetTokenAudiencePrefix(appId)}/access_as_user`;
6
+ }
7
+ export function GetMSALSiteScope(siteUrl: string) {
8
+ return `https://${new URL(siteUrl).hostname}`;
9
+ }
@@ -0,0 +1,92 @@
1
+ import { AzureEnvironment, ITenantInfo, isNullOrEmptyString, isValidGuid, promiseOnce } from "../_dependencies";
2
+ import { GetJson } from "../rest";
3
+
4
+ export function DiscoverTenantInfo(hostName: string) {
5
+ hostName = hostName.toLowerCase();
6
+ return promiseOnce(`DiscoverTenantInfo|${hostName}`, async () => {
7
+ let data: ITenantInfo = {
8
+ environment: AzureEnvironment.Production,
9
+ idOrName: null,
10
+ authorityUrl: null,
11
+ valid: false
12
+ };
13
+
14
+ let tenantId: string = null;
15
+ let friendlyName: string = null;
16
+
17
+ try {
18
+ if (hostName.indexOf(".sharepoint.") !== -1) {
19
+ let hostParts = hostName.split('.');//should be xxx.sharepoint.com or xxx.sharepoint.us
20
+ let firstHostPart = hostParts[0];
21
+ let lastHostPart = hostParts[hostParts.length - 1] === "us" || hostParts[hostParts.length - 1] === "de" ? hostParts[hostParts.length - 1] : "com";
22
+ if (firstHostPart.endsWith("-admin")) firstHostPart = firstHostPart.substring(0, firstHostPart.length - 6);
23
+ friendlyName = `${firstHostPart}.onmicrosoft.${lastHostPart}`;
24
+ }
25
+ else friendlyName = hostName;//could be an exchange email domain, or bpos customer
26
+
27
+ let config = await GetJson<{
28
+ token_endpoint: string;//https://login.microsoftonline.com/7d034656-be03-457d-8d82-60e90cf5f400/oauth2/token
29
+ cloud_instance_name: string;//microsoftonline.com
30
+ token_endpoint_auth_methods_supported: string[];// ["client_secret_post", "private_key_jwt", "client_secret_basic"]
31
+ response_modes_supported: string[];// ["query", "fragment", "form_post"]
32
+ response_types_supported: string[];// ["code", "id_token", "code id_token", "token id_token", "token"]
33
+ scopes_supported: string[];// ["openid"]
34
+ issuer: string;//https://sts.windows.net/7d034656-be03-457d-8d82-60e90cf5f400/
35
+ authorization_endpoint: string;//https://login.microsoftonline.com/7d034656-be03-457d-8d82-60e90cf5f400/oauth2/authorize
36
+ device_authorization_endpoint: string;//https://login.microsoftonline.com/7d034656-be03-457d-8d82-60e90cf5f400/oauth2/devicecode
37
+ end_session_endpoint: string;//https://login.microsoftonline.com/7d034656-be03-457d-8d82-60e90cf5f400/oauth2/logout
38
+ userinfo_endpoint: string;//https://login.microsoftonline.com/7d034656-be03-457d-8d82-60e90cf5f400/openid/userinfo
39
+ tenant_region_scope: string;//NA
40
+ cloud_graph_host_name: string;//graph.windows.net
41
+ msgraph_host: string;//graph.microsoft.com
42
+ }>(`https://login.microsoftonline.com/${friendlyName}/v2.0/.well-known/openid-configuration`);
43
+
44
+ let endpoint = config.token_endpoint;//https://xxxx/{tenant}/....
45
+ tenantId = endpoint.replace("//", "/").split('/')[2];//replace :// with :/ split by / and take the second part.
46
+ let instance = config.cloud_instance_name;//microsoftonline.us
47
+
48
+ data.environment = GetEnvironmentFromACSEndPoint(instance);
49
+ if (!isNullOrEmptyString(tenantId) || isValidGuid(tenantId))
50
+ data.idOrName = tenantId;
51
+ else
52
+ data.idOrName = friendlyName;
53
+
54
+ data.authorityUrl = `${GetAzureADLoginEndPoint(data.environment)}/${data.idOrName}`;
55
+ data.valid = true;
56
+ }
57
+ catch (e) { }
58
+
59
+ return data;
60
+ });
61
+ }
62
+
63
+ export function AutoDiscoverTenantInfo() {
64
+ return DiscoverTenantInfo(window.location.hostname.toLowerCase());
65
+ }
66
+
67
+ export function GetEnvironmentFromACSEndPoint(ACSEndPoint: string): AzureEnvironment {
68
+ switch (ACSEndPoint) {
69
+ case "microsoftonline.us":
70
+ return AzureEnvironment.USGovernment;
71
+ case "microsoftonline.de":
72
+ return AzureEnvironment.Germany;
73
+ case "accesscontrol.chinacloudapi.cn":
74
+ return AzureEnvironment.China;
75
+ case "windows-ppe.net":
76
+ return AzureEnvironment.PPE;
77
+ case "accesscontrol.windows.net":
78
+ default:
79
+ return AzureEnvironment.Production;
80
+ }
81
+ }
82
+ export function GetAzureADLoginEndPoint(environment: AzureEnvironment): string {
83
+ switch (environment) {
84
+ case AzureEnvironment.Germany: return "https://login.microsoftonline.de";
85
+ case AzureEnvironment.China: return "https://login.chinacloudapi.cn";
86
+ case AzureEnvironment.USGovernment: return "https://login.microsoftonline.us";
87
+ case AzureEnvironment.PPE: return "https://login.windows-ppe.net";
88
+ case AzureEnvironment.Production:
89
+ default:
90
+ return "https://login.microsoftonline.com";
91
+ }
92
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./common";
2
+ export * from "./discovery";
3
+
@@ -9,5 +9,6 @@ export * from './localstoragecache';
9
9
  export * from './rest';
10
10
  export * from './sharepoint.rest';
11
11
  export * from './sod';
12
+ export * from './auth';
12
13
  export const script = _script;
13
14
  export const Sod = _sod;