@thzero/library_server 0.17.13 → 0.17.14
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/package.json +3 -3
- package/repository/index.js +8 -0
- package/service/baseSecurity.js +94 -83
- package/service/config.js +23 -18
- package/service/news/base.js +24 -18
- package/service/plans.js +6 -2
- package/service/utility.js +39 -28
- package/service/version.js +15 -10
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thzero/library_server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.17.
|
|
4
|
+
"version": "0.17.14",
|
|
5
5
|
"version_major": 0,
|
|
6
6
|
"version_minor": 17,
|
|
7
|
-
"version_patch":
|
|
8
|
-
"version_date": "
|
|
7
|
+
"version_patch": 14,
|
|
8
|
+
"version_date": "07/03/2023",
|
|
9
9
|
"description": "An opinionated library of common functionality to bootstrap an API using either Fastify or Koa as the web server.",
|
|
10
10
|
"author": "thZero",
|
|
11
11
|
"license": "MIT",
|
package/repository/index.js
CHANGED
|
@@ -130,6 +130,14 @@ class Repository {
|
|
|
130
130
|
return Response.error(clazz, method, message, err, code, errors, correlationId);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
_errorResponse(clazz, method, value, code, correlationId) {
|
|
134
|
+
if (code)
|
|
135
|
+
this._logger.error(clazz, method, 'code', code, correlationId);
|
|
136
|
+
const response = Response.error(null, null, null, null, code, null, correlationId);
|
|
137
|
+
response.results = value;
|
|
138
|
+
return response;
|
|
139
|
+
}
|
|
140
|
+
|
|
133
141
|
_hasFailed(response) {
|
|
134
142
|
return Response.hasFailed(response);
|
|
135
143
|
}
|
package/service/baseSecurity.js
CHANGED
|
@@ -20,95 +20,107 @@ class BaseSecurityService extends Service {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async authorizationCheckClaims(correlationId, claims, roles, logical) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
logical
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
23
|
+
try {
|
|
24
|
+
if (!claims)
|
|
25
|
+
return false;
|
|
26
|
+
if (!(claims && Array.isArray(claims)))
|
|
27
|
+
return false;
|
|
28
|
+
if (!roles)
|
|
29
|
+
return true;
|
|
30
|
+
|
|
31
|
+
if (String.isNullOrEmpty(logical) || (logical !== BaseSecurityService.logicalAnd) || (logical !== BaseSecurityService.logicalOr))
|
|
32
|
+
logical = BaseSecurityService.logicalOr;
|
|
33
|
+
|
|
34
|
+
let success = (logical === BaseSecurityService.logicalOr ? false : true);
|
|
35
|
+
|
|
36
|
+
let result;
|
|
37
|
+
let roleAct;
|
|
38
|
+
let roleObj;
|
|
39
|
+
let roleParts;
|
|
40
|
+
for (const claim of claims) {
|
|
41
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckClaims', 'authorization.claim', claim, correlationId);
|
|
42
|
+
|
|
43
|
+
for (const role of roles) {
|
|
44
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckClaims', 'role', role, correlationId);
|
|
45
|
+
|
|
46
|
+
roleParts = role.split('.');
|
|
47
|
+
if (roleParts && roleParts.length < 1)
|
|
48
|
+
success = false;
|
|
49
|
+
|
|
50
|
+
roleObj = roleParts[0];
|
|
51
|
+
roleAct = roleParts.length >= 2 ? roleParts[1] : null
|
|
52
|
+
|
|
53
|
+
result = await this.validate(claim, null, roleObj, roleAct);
|
|
54
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckClaims', 'result', result, correlationId);
|
|
55
|
+
if (logical === BaseSecurityService.logicalOr)
|
|
56
|
+
success = success || result;
|
|
57
|
+
else
|
|
58
|
+
success = success && result;
|
|
59
|
+
}
|
|
58
60
|
}
|
|
59
|
-
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
return success;
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
this._error('BaseSecurityService', 'authorizationCheckClaims', null, err, null, null, correlationId);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
async authorizationCheckRoles(correlationId, user, roles, logical) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
logical
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
71
|
+
try {
|
|
72
|
+
if (!user)
|
|
73
|
+
return false;
|
|
74
|
+
if (!roles)
|
|
75
|
+
return true;
|
|
76
|
+
|
|
77
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckRoles', 'user', user, correlationId);
|
|
78
|
+
if (!(user && user.roles && Array.isArray(user.roles)))
|
|
79
|
+
return false;
|
|
80
|
+
|
|
81
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckRoles', 'logical', logical, correlationId);
|
|
82
|
+
|
|
83
|
+
if (String.isNullOrEmpty(logical) || (logical !== BaseSecurityService.logicalAnd) || (logical !== BaseSecurityService.logicalOr))
|
|
84
|
+
logical = BaseSecurityService.logicalOr;
|
|
85
|
+
|
|
86
|
+
let success = (logical === BaseSecurityService.logicalOr ? false : true);
|
|
87
|
+
|
|
88
|
+
let result;
|
|
89
|
+
let roleAct;
|
|
90
|
+
let roleObj;
|
|
91
|
+
let roleParts;
|
|
92
|
+
for (const userRole of user.roles) {
|
|
93
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckRoles', 'userRole', userRole, correlationId);
|
|
94
|
+
|
|
95
|
+
for (const role of roles) {
|
|
96
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckRoles', 'role', role, correlationId);
|
|
97
|
+
|
|
98
|
+
roleParts = role.split('.');
|
|
99
|
+
if (roleParts && roleParts.length < 1)
|
|
100
|
+
success = false;
|
|
101
|
+
|
|
102
|
+
roleObj = roleParts[0];
|
|
103
|
+
roleAct = roleParts.length >= 2 ? roleParts[1] : null
|
|
104
|
+
|
|
105
|
+
result = await this.validate(correlationId, userRole, null, roleObj, roleAct);
|
|
106
|
+
this._logger.debug('BaseSecurityService', 'authorizationCheckRoles', 'result', result, correlationId);
|
|
107
|
+
if (logical === BaseSecurityService.logicalOr) {
|
|
108
|
+
if (result)
|
|
109
|
+
return result;
|
|
110
|
+
|
|
111
|
+
success = false;
|
|
112
|
+
}
|
|
113
|
+
else
|
|
114
|
+
success = success && result;
|
|
105
115
|
}
|
|
106
|
-
else
|
|
107
|
-
success = success && result;
|
|
108
116
|
}
|
|
109
|
-
}
|
|
110
117
|
|
|
111
|
-
|
|
118
|
+
return success;
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
this._error('BaseSecurityService', 'authorizationCheckRoles', null, err, null, null, correlationId);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
112
124
|
}
|
|
113
125
|
|
|
114
126
|
initializeRoles(correlationId, requestRoles, roles) {
|
|
@@ -157,8 +169,7 @@ class BaseSecurityService extends Service {
|
|
|
157
169
|
array.push(act);
|
|
158
170
|
|
|
159
171
|
const role = array.join(':');
|
|
160
|
-
|
|
161
|
-
return results;
|
|
172
|
+
return await this._enforcer.can(sub, role);
|
|
162
173
|
}
|
|
163
174
|
|
|
164
175
|
_initModel() {
|
package/service/config.js
CHANGED
|
@@ -6,25 +6,30 @@ class ServerConfigService extends ConfigService {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
getBackend(key) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
9
|
+
try {
|
|
10
|
+
if (String.isNullOrEmpty(key))
|
|
11
|
+
return null;
|
|
12
|
+
|
|
13
|
+
if (!this._config)
|
|
14
|
+
return null;
|
|
15
|
+
|
|
16
|
+
const configBackend = this._config.get('backend', null);
|
|
17
|
+
if (!configBackend)
|
|
18
|
+
return null;
|
|
19
|
+
|
|
20
|
+
if (!Array.isArray(configBackend))
|
|
21
|
+
return null;
|
|
22
|
+
|
|
23
|
+
key = key.toLowerCase();
|
|
24
|
+
for (const item of configBackend) {
|
|
25
|
+
if (item.key.toLowerCase() === key)
|
|
26
|
+
return item;
|
|
27
|
+
}
|
|
26
28
|
}
|
|
27
|
-
|
|
29
|
+
catch (err) {
|
|
30
|
+
this._error('ServerConfigService', 'getBackend', null, err, null, null, correlationId);
|
|
31
|
+
}
|
|
32
|
+
|
|
28
33
|
return null;
|
|
29
34
|
}
|
|
30
35
|
}
|
package/service/news/base.js
CHANGED
|
@@ -21,28 +21,34 @@ class BaseNewsService extends Service {
|
|
|
21
21
|
|
|
22
22
|
async latest(correlationId, user, timestamp) {
|
|
23
23
|
this._enforceNotEmpty('BaseNewsService', 'latest', timestamp, 'timestamp', correlationId);
|
|
24
|
+
|
|
24
25
|
try {
|
|
25
|
-
|
|
26
|
+
try {
|
|
27
|
+
timestamp = parseInt(timestamp);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
return this._error('BaseNewsService', 'latest', 'Invalid timestamp.', null, err, null, correlationId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const validationCheckNewsTiemstampResponse = this._serviceValidation.check(correlationId, this._serviceValidationNews.newsTimestampSchema, timestamp, null, 'news');
|
|
34
|
+
if (!validationCheckNewsTiemstampResponse.success)
|
|
35
|
+
return validationCheckNewsTiemstampResponse;
|
|
36
|
+
|
|
37
|
+
const respositoryResponse = await this._repositoryNews.latest(correlationId, timestamp);
|
|
38
|
+
if (this._hasFailed(respositoryResponse))
|
|
39
|
+
return respositoryResponse;
|
|
40
|
+
|
|
41
|
+
let data = respositoryResponse.results.data;
|
|
42
|
+
if (data)
|
|
43
|
+
data = data.filter(l => (l.requiresAuth && user) || !l.requiresAuth);
|
|
44
|
+
respositoryResponse.results.data = data;
|
|
45
|
+
respositoryResponse.results.count = data.length;
|
|
46
|
+
|
|
47
|
+
return respositoryResponse;
|
|
26
48
|
}
|
|
27
49
|
catch (err) {
|
|
28
|
-
return this._error('BaseNewsService', 'latest',
|
|
50
|
+
return this._error('BaseNewsService', 'latest', null, err, null, null, correlationId);
|
|
29
51
|
}
|
|
30
|
-
|
|
31
|
-
const validationCheckNewsTiemstampResponse = this._serviceValidation.check(correlationId, this._serviceValidationNews.newsTimestampSchema, timestamp, null, 'news');
|
|
32
|
-
if (!validationCheckNewsTiemstampResponse.success)
|
|
33
|
-
return validationCheckNewsTiemstampResponse;
|
|
34
|
-
|
|
35
|
-
const respositoryResponse = await this._repositoryNews.latest(correlationId, timestamp);
|
|
36
|
-
if (this._hasFailed(respositoryResponse))
|
|
37
|
-
return respositoryResponse;
|
|
38
|
-
|
|
39
|
-
let data = respositoryResponse.results.data;
|
|
40
|
-
if (data)
|
|
41
|
-
data = data.filter(l => (l.requiresAuth && user) || !l.requiresAuth);
|
|
42
|
-
respositoryResponse.results.data = data;
|
|
43
|
-
respositoryResponse.results.count = data.length;
|
|
44
|
-
|
|
45
|
-
return respositoryResponse;
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
get _repositoryNews() {
|
package/service/plans.js
CHANGED
|
@@ -16,8 +16,12 @@ class PlansService extends Service {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
async listing(correlationId) {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
try {
|
|
20
|
+
return await this._repositoryPlans.listing(correlationId);
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return this._error('PlansService', 'correlationId', null, err, null, null, correlationId);
|
|
24
|
+
}
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
get _repositoryPlans() {
|
package/service/utility.js
CHANGED
|
@@ -8,6 +8,8 @@ import LibraryCommonUtility from '@thzero/library_common/utility/index.js';
|
|
|
8
8
|
|
|
9
9
|
import Service from './index.js';
|
|
10
10
|
|
|
11
|
+
import Response from '@thzero/library_common/response/index.js';
|
|
12
|
+
|
|
11
13
|
class UtilityService extends Service {
|
|
12
14
|
constructor() {
|
|
13
15
|
super();
|
|
@@ -65,41 +67,50 @@ class UtilityService extends Service {
|
|
|
65
67
|
this._initializeResponse = response;
|
|
66
68
|
return response;
|
|
67
69
|
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
return this._error('UtilityService', 'initialize', null, err, null, null, correlationId);
|
|
72
|
+
}
|
|
68
73
|
finally {
|
|
69
74
|
release();
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
|
|
73
78
|
async logger(content, correlationId) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
79
|
+
try {
|
|
80
|
+
if (!content)
|
|
81
|
+
return this._error('UtilityService', 'logger');
|
|
82
|
+
|
|
83
|
+
const type = content.type;
|
|
84
|
+
switch(type) {
|
|
85
|
+
case 'DEBUG':
|
|
86
|
+
this._logger.debug('UtilityService', 'logger', content.message, content.data, correlationId, true);
|
|
87
|
+
break;
|
|
88
|
+
case 'ERROR':
|
|
89
|
+
this._logger.error('UtilityService', 'logger', content.message, content.data, correlationId, true);
|
|
90
|
+
break;
|
|
91
|
+
case 'EXCEPTION':
|
|
92
|
+
this._logger.exception('UtilityService', 'logger', content.ex, correlationId, true);
|
|
93
|
+
break;
|
|
94
|
+
case 'FATAL':
|
|
95
|
+
this._logger.fatal('UtilityService', 'logger', content.message, content.data, correlationId, true);
|
|
96
|
+
break;
|
|
97
|
+
case 'INFO':
|
|
98
|
+
this._logger.info('UtilityService', 'logger', content.message, content.data, correlationId, true);
|
|
99
|
+
break;
|
|
100
|
+
case 'TRACE':
|
|
101
|
+
this._logger.trace('UtilityService', 'logger', content.message, content.data, correlationId, true);
|
|
102
|
+
break;
|
|
103
|
+
case 'WARN':
|
|
104
|
+
this._logger.warn('UtilityService', 'logger', content.message, content.data, correlationId, true);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return this._success(correlationId);
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
console.log(`UtilityService.initialize - ${correlationId}`, err);
|
|
112
|
+
return Response.error('ServerConfigService', 'getBackend', null, err, null, null, correlationId);
|
|
100
113
|
}
|
|
101
|
-
|
|
102
|
-
return this._success(correlationId);
|
|
103
114
|
}
|
|
104
115
|
|
|
105
116
|
async openSource(correlationId) {
|
package/service/version.js
CHANGED
|
@@ -5,16 +5,21 @@ import Service from './index.js';
|
|
|
5
5
|
|
|
6
6
|
class VersionService extends Service {
|
|
7
7
|
async version(correlationId) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
try {
|
|
9
|
+
const filePath = path.join(process.cwd(), 'package.json');
|
|
10
|
+
const file = fs.readFileSync(filePath, 'utf8');
|
|
11
|
+
if (String.isNullOrEmpty(file))
|
|
12
|
+
throw Error('Invalid package.json file for versioning; expected in the <app root> folder.');
|
|
13
|
+
|
|
14
|
+
const packageObj = JSON.parse(file);
|
|
15
|
+
if (!packageObj)
|
|
16
|
+
throw Error('Invalid package.json file for versioning.');
|
|
17
|
+
|
|
18
|
+
return this._generate(correlationId, packageObj.version_major, packageObj.version_minor, packageObj.version_patch, packageObj.version_date);
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
return this._error('VersionService', 'version', null, err, null, null, correlationId);
|
|
22
|
+
}
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
_generate(correlationId, version_major, version_minor, version_patch, version_date) {
|