zavadil-ts-common 2.2.6 → 2.2.8

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.
@@ -1,107 +1,104 @@
1
- import { StringUtil, ObjectUtil } from "../util";
1
+ import {StringUtil, ObjectUtil} from "../util";
2
2
  import {PERMISSION_LEVELS, PermissionLevel, TokenResponsePayloadBase} from "./Types";
3
3
 
4
4
  export class OAuthUtil {
5
- static isValidToken(token?: TokenResponsePayloadBase | null): boolean {
6
- return (
7
- ObjectUtil.notEmpty(token) &&
8
- StringUtil.notBlank(token.token) &&
9
- !OAuthUtil.isTokenExpired(token)
10
- );
11
- }
12
5
 
13
- static isTokenExpired(token?: TokenResponsePayloadBase | null): boolean {
14
- if (token === undefined || token === null) return false;
15
- if (token.expires === undefined || token.expires === null) return false;
16
- return token.expires < new Date();
17
- }
6
+ static isValidToken(token?: TokenResponsePayloadBase | null): boolean {
7
+ return ObjectUtil.isObject(token) && StringUtil.notBlank(token.token) && !OAuthUtil.isTokenExpired(token);
8
+ }
18
9
 
19
- static isTokenReadyForRefresh(
20
- token?: TokenResponsePayloadBase | null,
21
- ): boolean {
22
- if (token === undefined || token === null) return false;
23
- if (OAuthUtil.isTokenExpired(token)) return false;
24
- if (token.expires === undefined || token.expires === null) return false;
25
- const middle = new Date(
26
- (token.expires.getTime() + token.issuedAt.getTime()) / 2,
27
- );
28
- const now = new Date();
29
- return middle < now;
30
- }
10
+ static isTokenExpired(token?: TokenResponsePayloadBase | null): boolean {
11
+ if (token === undefined || token === null) return false;
12
+ if (token.expires === undefined || token.expires === null) return false;
13
+ return token.expires < new Date();
14
+ }
31
15
 
32
- public static getScopeString(privilege: string, level: PermissionLevel) {
33
- return `${level}:${privilege}`;
34
- }
16
+ static isTokenReadyForRefresh(
17
+ token?: TokenResponsePayloadBase | null,
18
+ ): boolean {
19
+ if (token === undefined || token === null) return false;
20
+ if (OAuthUtil.isTokenExpired(token)) return false;
21
+ if (token.expires === undefined || token.expires === null) return false;
22
+ const middle = new Date(
23
+ (token.expires.getTime() + token.issuedAt.getTime()) / 2,
24
+ );
25
+ const now = new Date();
26
+ return middle < now;
27
+ }
35
28
 
36
- public static extractPrivilege(scope: string): string {
37
- const arr = scope.split(":");
38
- if (arr.length < 2) return "";
39
- return arr[1];
40
- }
29
+ public static getScopeString(privilege: string, level: PermissionLevel) {
30
+ return `${level}:${privilege}`;
31
+ }
41
32
 
42
- public static isPermissionLevel(value: string): value is PermissionLevel {
43
- return (PERMISSION_LEVELS as readonly string[]).includes(value);
44
- }
33
+ public static extractPrivilege(scope: string): string {
34
+ const arr = scope.split(":");
35
+ if (arr.length < 2) return "";
36
+ return arr[1];
37
+ }
45
38
 
46
- public static extractPermissionLevel(scope: string): PermissionLevel {
47
- const arr = scope.split(":");
48
- if (arr.length === 0) throw new Error(`Scope value ${scope} is invalid!`);
49
- const str = arr[0];
50
- if (!OAuthUtil.isPermissionLevel(str))
51
- throw new Error(`"${str} is not valid permission level!`);
52
- return str;
53
- }
39
+ public static isPermissionLevel(value: string): value is PermissionLevel {
40
+ return (PERMISSION_LEVELS as readonly string[]).includes(value);
41
+ }
54
42
 
55
- public static getLevel(level: PermissionLevel): number {
56
- switch (level) {
57
- case "admin":
58
- return 3;
59
- case "write":
60
- return 2;
61
- case "read":
62
- return 1;
63
- default:
64
- return 0;
65
- }
66
- }
43
+ public static extractPermissionLevel(scope: string): PermissionLevel {
44
+ const arr = scope.split(":");
45
+ if (arr.length === 0) throw new Error(`Scope value ${scope} is invalid!`);
46
+ const str = arr[0];
47
+ if (!OAuthUtil.isPermissionLevel(str))
48
+ throw new Error(`"${str} is not valid permission level!`);
49
+ return str;
50
+ }
67
51
 
68
- /**
69
- * Returns true if given scope grants permission for specific privilege on at least required level.
70
- *
71
- * @param ownedScope Existing scope, usually owned by user in form of access token
72
- * @param requiredScopeOrPrivilege Required privilege name or whole scope (omit minLevel)
73
- * @param minLevel Required minimal permission level
74
- */
75
- public static hasPermission(
76
- ownedScope: string,
77
- requiredScopeOrPrivilege: string,
78
- minLevel?: PermissionLevel,
79
- ): boolean {
80
- if (minLevel === undefined) {
81
- try {
82
- minLevel = OAuthUtil.extractPermissionLevel(requiredScopeOrPrivilege);
83
- requiredScopeOrPrivilege = OAuthUtil.extractPrivilege(
84
- requiredScopeOrPrivilege,
85
- );
86
- } catch (e) {
87
- minLevel = "admin";
88
- }
89
- }
52
+ public static getLevel(level: PermissionLevel): number {
53
+ switch (level) {
54
+ case "admin":
55
+ return 3;
56
+ case "write":
57
+ return 2;
58
+ case "read":
59
+ return 1;
60
+ default:
61
+ return 0;
62
+ }
63
+ }
90
64
 
91
- const ownedLevel = OAuthUtil.extractPermissionLevel(ownedScope);
92
- // owned level must be at least equal to the required
93
- if (OAuthUtil.getLevel(ownedLevel) < OAuthUtil.getLevel(minLevel))
94
- return false;
65
+ /**
66
+ * Returns true if given scope grants permission for specific privilege on at least required level.
67
+ *
68
+ * @param ownedScope Existing scope, usually owned by user in form of access token
69
+ * @param requiredScopeOrPrivilege Required privilege name or whole scope (omit minLevel)
70
+ * @param minLevel Required minimal permission level
71
+ */
72
+ public static hasPermission(
73
+ ownedScope: string,
74
+ requiredScopeOrPrivilege: string,
75
+ minLevel?: PermissionLevel,
76
+ ): boolean {
77
+ if (minLevel === undefined) {
78
+ try {
79
+ minLevel = OAuthUtil.extractPermissionLevel(requiredScopeOrPrivilege);
80
+ requiredScopeOrPrivilege = OAuthUtil.extractPrivilege(
81
+ requiredScopeOrPrivilege,
82
+ );
83
+ } catch (e) {
84
+ minLevel = "admin";
85
+ }
86
+ }
95
87
 
96
- const ownedPrivilege = OAuthUtil.extractPrivilege(ownedScope);
97
- // super admin, has privilege for all resources
98
- if (ownedPrivilege === "*") return true;
99
- // user has exactly the required privilege
100
- if (ownedPrivilege === requiredScopeOrPrivilege) return true;
101
- // now the only possibility is that user has privilege ending with * covering the required privilege
102
- if (!ownedPrivilege?.endsWith("/*")) return false;
88
+ const ownedLevel = OAuthUtil.extractPermissionLevel(ownedScope);
89
+ // owned level must be at least equal to the required
90
+ if (OAuthUtil.getLevel(ownedLevel) < OAuthUtil.getLevel(minLevel))
91
+ return false;
103
92
 
104
- const ownedParent = ownedPrivilege.replace("/*", "");
105
- return requiredScopeOrPrivilege?.startsWith(ownedParent) ?? false;
106
- }
93
+ const ownedPrivilege = OAuthUtil.extractPrivilege(ownedScope);
94
+ // super admin, has privilege for all resources
95
+ if (ownedPrivilege === "*") return true;
96
+ // user has exactly the required privilege
97
+ if (ownedPrivilege === requiredScopeOrPrivilege) return true;
98
+ // now the only possibility is that user has privilege ending with * covering the required privilege
99
+ if (!ownedPrivilege?.endsWith("/*")) return false;
100
+
101
+ const ownedParent = ownedPrivilege.replace("/*", "");
102
+ return requiredScopeOrPrivilege?.startsWith(ownedParent) ?? false;
103
+ }
107
104
  }
@@ -2,6 +2,10 @@ import { ObjectUtil } from "./ObjectUtil";
2
2
 
3
3
  export class ArrayUtil {
4
4
 
5
+ static isArray(arr: any): arr is Array<any> {
6
+ return Array.isArray(arr);
7
+ }
8
+
5
9
  static isEmpty(arr?: Array<any> | null): arr is null | undefined {
6
10
  return ObjectUtil.isEmpty(arr) || arr.length === 0;
7
11
  }
@@ -17,4 +17,9 @@ export class JsonUtil {
17
17
  static parse(json?: string | null): any {
18
18
  return JsonUtil.parseWithDates(json);
19
19
  }
20
+
21
+ static serialize(o: any): string {
22
+ return JSON.stringify(o);
23
+ }
24
+
20
25
  }
@@ -4,6 +4,11 @@ export class NumberUtil {
4
4
  return n === undefined || n === null || Number.isNaN(n);
5
5
  }
6
6
 
7
+ static isNumber(n: any): n is number {
8
+ if (NumberUtil.isEmpty(n)) return false;
9
+ return typeof n === "number";
10
+ }
11
+
7
12
  static notEmpty(n?: number | null): n is number {
8
13
  return !NumberUtil.isEmpty(n);
9
14
  }
@@ -4,8 +4,13 @@ export class ObjectUtil {
4
4
  return obj === undefined || obj === null;
5
5
  }
6
6
 
7
- static notEmpty(obj: any): obj is object {
8
- return !ObjectUtil.isEmpty(obj);
7
+ static isObject(o: any): o is Record<string, unknown> {
8
+ if (ObjectUtil.isEmpty(o)) return false;
9
+ return typeof o === "object";
10
+ }
11
+
12
+ static notEmpty(obj: any): obj is Record<string, unknown> {
13
+ return !ObjectUtil.isObject(obj);
9
14
  }
10
15
 
11
16
  static clone<T>(obj: T): T {
@@ -1,15 +1,25 @@
1
1
  import {HashUtil} from "./HashUtil";
2
2
  import {ObjectUtil} from "./ObjectUtil";
3
+ import {NumberUtil} from "./NumberUtil";
4
+ import {ArrayUtil} from "./ArrayUtil";
5
+ import {JsonUtil} from "./JsonUtil";
3
6
 
4
7
  export class StringUtil {
8
+
5
9
  static isString(str: any): str is string {
10
+ if (ObjectUtil.isEmpty(str)) return false;
6
11
  return typeof str === "string";
7
12
  }
8
13
 
9
14
  static toString(s: any): string {
10
15
  if (StringUtil.isString(s)) return s;
11
- if (StringUtil.isString(s.message)) return s.message; // Errors
12
- return s?.toString?.() ?? "";
16
+ if (NumberUtil.isNumber(s)) return s.toString();
17
+ if (ArrayUtil.isArray(s)) return `[${s.map(i => StringUtil.toString(i)).join(',')}]`;
18
+ if (ObjectUtil.isObject(s)) {
19
+ if (StringUtil.isString(s.message)) return s.message; // Errors
20
+ return JsonUtil.serialize(s);
21
+ }
22
+ return StringUtil.getNonEmpty(s);
13
23
  }
14
24
 
15
25
  static isEmpty(str: string | null | undefined): str is null | undefined {
@@ -1,4 +1,23 @@
1
- import {StringUtil, JsonUtil, RestClient, UrlUtil, EmailUtil} from '../src';
1
+ import {StringUtil, JsonUtil, RestClient, UrlUtil, EmailUtil, ObjectUtil, ArrayUtil} from '../src';
2
+
3
+ describe('testing ObjectUtil', () => {
4
+ test('isEmpty', () => {
5
+ expect(ObjectUtil.isEmpty(undefined)).toBe(true);
6
+ expect(ObjectUtil.isEmpty(null)).toBe(true);
7
+ expect(ObjectUtil.isEmpty([])).toBe(false);
8
+ expect(ObjectUtil.isEmpty({})).toBe(false);
9
+ expect(ObjectUtil.isEmpty('')).toBe(false);
10
+ expect(ObjectUtil.isEmpty('test')).toBe(false);
11
+ });
12
+ test('isObject', () => {
13
+ expect(ObjectUtil.isObject(undefined)).toBe(false);
14
+ expect(ObjectUtil.isObject(null)).toBe(false);
15
+ expect(ObjectUtil.isObject([])).toBe(true);
16
+ expect(ObjectUtil.isObject({})).toBe(true);
17
+ expect(ObjectUtil.isObject('')).toBe(false);
18
+ expect(ObjectUtil.isObject('test')).toBe(false);
19
+ });
20
+ });
2
21
 
3
22
  describe('testing StringUtil', () => {
4
23
  test('isEmpty', () => {
@@ -15,6 +34,24 @@ describe('testing StringUtil', () => {
15
34
  expect(StringUtil.isBlank(null)).toBe(true);
16
35
  expect(StringUtil.isBlank(undefined)).toBe(true);
17
36
  });
37
+ test('isString', () => {
38
+ expect(StringUtil.isString('test')).toBe(true);
39
+ expect(StringUtil.isString(' ')).toBe(true);
40
+ expect(StringUtil.isString('')).toBe(true);
41
+ expect(StringUtil.isString(null)).toBe(false);
42
+ expect(StringUtil.isString(undefined)).toBe(false);
43
+ expect(StringUtil.isString({})).toBe(false);
44
+ expect(StringUtil.isString([])).toBe(false);
45
+ });
46
+ test('toString', () => {
47
+ expect(StringUtil.toString('test')).toBe('test');
48
+ expect(StringUtil.toString(' ')).toBe(' ');
49
+ expect(StringUtil.toString('')).toBe('');
50
+ expect(StringUtil.toString(null)).toBe('');
51
+ expect(StringUtil.toString(undefined)).toBe('');
52
+ expect(StringUtil.toString({})).toBe('{}');
53
+ expect(StringUtil.toString([1, 2, 3])).toBe('[1,2,3]');
54
+ });
18
55
  test('getNonEmpty', () => {
19
56
  expect(StringUtil.getNonEmpty('test')).toBe('test');
20
57
  expect(StringUtil.getNonEmpty('', 'test')).toBe('test');
@@ -30,6 +67,24 @@ describe('testing StringUtil', () => {
30
67
  });
31
68
  });
32
69
 
70
+ describe('testing ArrayUtil', () => {
71
+ test('isEmpty', () => {
72
+ expect(ArrayUtil.isEmpty(undefined)).toBe(true);
73
+ expect(ArrayUtil.isEmpty(null)).toBe(true);
74
+ expect(ArrayUtil.isEmpty([])).toBe(true);
75
+ expect(ArrayUtil.isEmpty([1,2,3])).toBe(false);
76
+ });
77
+ test('isArray', () => {
78
+ expect(ArrayUtil.isArray(undefined)).toBe(false);
79
+ expect(ArrayUtil.isArray(null)).toBe(false);
80
+ expect(ArrayUtil.isArray([])).toBe(true);
81
+ expect(ArrayUtil.isArray([1,2,3])).toBe(true);
82
+ expect(ArrayUtil.isArray({})).toBe(false);
83
+ expect(ArrayUtil.isArray('')).toBe(false);
84
+ expect(ArrayUtil.isArray('test')).toBe(false);
85
+ });
86
+ });
87
+
33
88
  describe('testing JsonUtil', () => {
34
89
  test('parseWithDates', () => {
35
90
  const myObj = {
@@ -37,7 +92,7 @@ describe('testing JsonUtil', () => {
37
92
  sval: "str",
38
93
  nval: 13
39
94
  }
40
- const myStr = JSON.stringify(myObj);
95
+ const myStr = JsonUtil.serialize(myObj);
41
96
  const parsed = JsonUtil.parseWithDates(myStr);
42
97
 
43
98
  expect(typeof parsed.dval).toBe('object');