@nsshunt/stsdatamanagement 1.12.10 → 1.12.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/databaseutils.js CHANGED
@@ -1,13 +1,10 @@
1
1
  const prompts = require('prompts');
2
- const fs = require('fs');
3
2
  require('colors');
4
- //let crypto = require('crypto');
5
3
  const goptions = require('@nsshunt/stsconfig').$options;
6
4
 
7
5
  const { PGPoolManager } = require('./pgpoolmanager');
8
6
  const { PGAccessLayer } = require('./pgaccesslayer');
9
7
  const { PGUtils } = require('./pgutils');
10
- const { BLCAuth } = require('./blcauth');
11
8
  const { DataGenerator } = require('./datagenerator.js');
12
9
 
13
10
  class DatabaseUtils
@@ -21,108 +18,12 @@ class DatabaseUtils
21
18
  this.#debug = require('debug')(this.#ns);
22
19
  this.#accessLayer = accessLayer;
23
20
  }
24
-
25
- #_RegisterRolesAndPermissions = async(blcauth) => {
26
- this.#debug(`Registering Roles and Role Permissions.`.yellow);
27
- console.log(`Registering Roles and Role Permissions.`.yellow);
28
- const rolePermissionFile = `${goptions.databasescriptfolder}/role-permission.json`;
29
- const rawdata = fs.readFileSync(rolePermissionFile);
30
- let rolePermissions = JSON.parse(rawdata);
31
- for (const [, rolePermission] of Object.entries(rolePermissions)) {
32
- let retVal = await blcauth.AddRolePermissions(rolePermission);
33
- if (retVal.status !== 200) {
34
- console.log(`Role Permission registered: ${JSON.stringify(retVal)}`.red);
35
- return false;
36
- } else {
37
- console.log(`Role Permission registered: ${JSON.stringify(retVal)}`);
38
- }
39
- }
40
- return true;
41
- }
42
-
43
- #_RegisterUsersAndRoles = async(blcauth) => {
44
- this.#debug(`Registering Users and Roles.`.yellow);
45
- console.log(`Registering Users and Roles.`.yellow);
46
- const roleFile = `${goptions.databasescriptfolder}/user-role.json`;
47
- let rawdata = fs.readFileSync(roleFile);
48
- let userroles = JSON.parse(rawdata);
49
- for (const [, user] of Object.entries(userroles)) {
50
- let retVal = await blcauth.AddUser(user);
51
- if (retVal.status !== 200) {
52
- console.log(`Role registered: ${JSON.stringify(retVal)}`.red);
53
- return false;
54
- } else {
55
- console.log(`Role registered: ${JSON.stringify(retVal)}`);
56
- }
57
- }
58
- return true;
59
- }
60
-
61
- #_RegisterTestingUsersAndRoles = async(blcauth) => {
62
- this.#debug(`Registering Test Users and Roles.`.yellow);
63
- console.log(`Registering Test Users and Roles.`.yellow);
64
- for (let i=0; i < 10; i++) {
65
- let userNoStr = i.toString().padStart(2, '0');
66
- let user = {
67
- name: `Test User ${userNoStr}`,
68
- email: `user${userNoStr}@stsmda.com.au`,
69
- password: `user${userNoStr}password`,
70
- roles: [ ]
71
- }
72
- let retVal = await blcauth.AddUser(user);
73
- if (retVal.status !== 200) {
74
- console.log(`User NOT registered: ${JSON.stringify(retVal)}`.red);
75
- return false;
76
- } else {
77
- console.log(`User registered: ${JSON.stringify(retVal)}`);
78
- }
79
- }
80
- return true;
81
- }
82
-
83
- #_RegisterApplications = async(blcauth) => {
84
- this.#debug(`Registering Applications.`.yellow);
85
- console.log(`Registering Applications.`.yellow);
86
- const roleFile = `${goptions.databasescriptfolder}/applications.json`;
87
- let rawdata = fs.readFileSync(roleFile);
88
- let applications = JSON.parse(rawdata);
89
- for (const [, application] of Object.entries(applications)) {
90
- //application.clientSecret = crypto.randomBytes(32).toString('base64');
91
- let retVal = await blcauth.AddApplication(application);
92
- if (retVal.status !== 200) {
93
- console.log(`Application registered: ${JSON.stringify(retVal)}`.red);
94
- return false;
95
- } else {
96
- console.log(`Application registered: ${JSON.stringify(retVal)}`);
97
- console.log(`Application secret : ${application.clientSecret}`);
98
- }
99
- }
100
- return true;
101
- }
102
-
103
- #_RegisterAPIs = async(blcauth) => {
104
- this.#debug(`Registering APIs.`.yellow);
105
- console.log(`Registering APIs.`.yellow);
106
- const roleFile = `${goptions.databasescriptfolder}/apis.json`;
107
- let rawdata = fs.readFileSync(roleFile);
108
- let apis = JSON.parse(rawdata);
109
- for (const [, api] of Object.entries(apis)) {
110
- let retVal = await blcauth.AddAPI(api);
111
- if (retVal.status !== 200) {
112
- console.log(`API registered: ${JSON.stringify(retVal)}`.red);
113
- return false;
114
- } else {
115
- console.log(`API registered: ${JSON.stringify(retVal)}`);
116
- }
117
- }
118
- return true;
119
- }
120
21
 
121
22
  // options ::= { start: <int>, entries: <int>, minextradata: <int>, maxextradata: <int>,
122
23
  // user: { name: <string>, password: <string>, email: <string> } }
123
- createfreshdatabase = async (options) =>
24
+ CreateDatabase = async (options) =>
124
25
  {
125
- let fname = 'createfreshdatabase';
26
+ let fname = 'CreateDatabase';
126
27
  const { start, entries, minextradata, maxextradata } = options;
127
28
  let builddbscript = `${goptions.databasescriptfolder}/builddb.sql`;
128
29
  this.#debug(`Database Build Script: [${builddbscript}]`.yellow);
@@ -149,6 +50,7 @@ class DatabaseUtils
149
50
  this.#debug(`Building database assets (tables, functions, etc.).`.yellow);
150
51
  await localAccesslayer.executedbscript(builddbscript);
151
52
 
53
+ //@@ make optional or move
152
54
  if (typeof entries !== 'undefined') {
153
55
  // Add new faker entries
154
56
  this.#debug(`Adding test data.`.yellow);
@@ -156,37 +58,11 @@ class DatabaseUtils
156
58
  await dg.RunAddFakerBulkInsert(start, entries, minextradata, maxextradata);
157
59
  }
158
60
 
159
- const blcauth = new BLCAuth(localAccesslayer);
160
- let status = true;
161
-
162
- status = await this.#_RegisterUsersAndRoles(blcauth);
163
- if (status) {
164
- status = await this.#_RegisterRolesAndPermissions(blcauth);
165
- }
166
- if (status) {
167
- status = await this.#_RegisterTestingUsersAndRoles(blcauth);
168
- }
169
- if (status) {
170
- status = await this.#_RegisterApplications(blcauth);
171
- }
172
- if (status) {
173
- status = await this.#_RegisterAPIs(blcauth);
174
- }
175
-
176
- if (status) {
177
- let retVal = await blcauth.GetUserPermissions('STSREST01ServiceUser@stsmda.com');
178
- console.log(`User Permissions: ${JSON.stringify(retVal)}`);
179
- }
180
-
181
61
  await localAccesslayer.enddatabase();
182
62
 
183
- if (status) {
184
- this.#debug(`Database successfully initiailized.`.green);
185
- console.log(`Database successfully initiailized.`.green);
186
- } else {
187
- this.#debug(`Database did not initiailize correctly.`.red);
188
- console.log(`Database did not initiailize correctly.`.red);
189
- }
63
+ //@@ double logging
64
+ this.#debug(`Database successfully initiailized.`.green);
65
+ console.log(`Database successfully initiailized.`.green);
190
66
  } catch (error)
191
67
  {
192
68
  console.error(`[${fname}]: Could not create fresh database: ${error}`);
@@ -200,14 +76,6 @@ class DatabaseUtils
200
76
  return retVal;
201
77
  };
202
78
 
203
- // user ::= { name: <string>, password: <string>, email: <string> }
204
- RegisterTestUser = async (user) =>
205
- {
206
- let retVal = await new BLCAuth(this.#accessLayer).registeruser(user);
207
- console.log(`User registered: ${JSON.stringify(retVal)}`);
208
- return retVal;
209
- };
210
-
211
79
  ExecuteDatabaseScript = async (scriptfile) =>
212
80
  {
213
81
  let retVal = await this.#accessLayer.executedbscript(scriptfile);
package/datagenerator.js CHANGED
@@ -175,7 +175,8 @@ class DataGenerator
175
175
 
176
176
 
177
177
  let pa = [ ];
178
- let numCPUs = require('os').cpus().length;
178
+ let numCPUs = goptions.useCPUs;
179
+ //let numCPUs = require('os').cpus().length;
179
180
  let blocksize = Math.floor(iterations / numCPUs);
180
181
  let lastBlockSize = blocksize + (iterations % numCPUs);
181
182
 
@@ -41,6 +41,18 @@
41
41
  "res01.delete"
42
42
  ]
43
43
  }
44
+ ],
45
+ "SPA": [
46
+ {
47
+ "clientName": "STSAuthenticateSPA",
48
+ "clientId": "v4qBrds3Autl/i86xT+5z0K53kJ/2hHTfxNo0QO/0Jk=",
49
+ "permissions": [
50
+ "res01.create",
51
+ "res01.read",
52
+ "res01.update",
53
+ "res01.delete"
54
+ ]
55
+ }
44
56
  ]
45
57
  },
46
58
 
package/dbaccess.js CHANGED
@@ -2,7 +2,6 @@ const { PGPoolManager } = require('./pgpoolmanager');
2
2
  const { L1Cache } = require('./l1cache');
3
3
  const { PGAccessLayer } = require('./pgaccesslayer');
4
4
  const { PGUtils } = require('./pgutils');
5
- const { BLCAuth } = require('./blcauth');
6
5
  const { DatabaseUtils } = require('./databaseutils');
7
6
  const { DataGenerator } = require('./datagenerator');
8
7
  const { CreateDatabase } = require('./setupdb');
@@ -13,7 +12,7 @@ const {
13
12
 
14
13
  module.exports = {
15
14
  // Utilities and Helpers
16
- PGPoolManager, L1Cache, PGAccessLayer, PGUtils, BLCAuth, DatabaseUtils, DataGenerator,
15
+ PGPoolManager, L1Cache, PGAccessLayer, PGUtils, DatabaseUtils, DataGenerator,
17
16
  // Errors
18
17
  STSDataManagementError, STSResourceNotFoundError, STSResourceMalformedError,
19
18
  STSDatabaseAccessError, STSInvalidCredentials, STSNotAuthorized,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nsshunt/stsdatamanagement",
3
- "version": "1.12.10",
3
+ "version": "1.12.14",
4
4
  "description": "STS Data Management Modules, Utilities and Services",
5
5
  "main": "dbaccess.js",
6
6
  "dependencies": {
package/setupdb.js CHANGED
@@ -5,7 +5,7 @@ const { DatabaseUtils } = require('./databaseutils.js');
5
5
 
6
6
  module.exports = {
7
7
  CreateDatabase: async() => {
8
- await new DatabaseUtils().createfreshdatabase({
8
+ await new DatabaseUtils().CreateDatabase({
9
9
  start: 0,
10
10
  entries: 10000,
11
11
  minextradata: 0,
package/blcauth.js DELETED
@@ -1,388 +0,0 @@
1
- const { status: { status } } = require('@nsshunt/stsutils');
2
- const bcrypt = require('bcryptjs');
3
- const { STSResourceNotFoundError, STSDatabaseAccessError, STSResourceMalformedError,
4
- STSNotAuthorized, STSInvalidCredentials } = require('./dberrors');
5
-
6
- class BLCAuth
7
- {
8
- static SYSTEM_USER_ID = "STS_SYSTEM";
9
- static USER_ID_PREFIX = "USR_";
10
- static ROLE_ID_PREFIX = "ROLE_";
11
- static APPLICATION_ID_PREFIX = "APP_";
12
- static API_ID_PREFIX = "API_";
13
-
14
- #accessLayer = null;
15
-
16
- constructor(accessLayer)
17
- {
18
- this.#accessLayer = accessLayer;
19
- }
20
-
21
- // Normally, register would be provided by a hardened dedicated authentication server.
22
- async AddUser(user)
23
- {
24
- let { name, password, email, roles } = user;
25
- const saltRounds = 10;
26
- try
27
- {
28
- let userid = BLCAuth.USER_ID_PREFIX + email;
29
- if (await this.#ResourceExists('User', userid)) {
30
- return {
31
- status: status.conflict,
32
- error: 'User already exists.',
33
- detail: { message: `User already exists: [${userid}]` }
34
- };
35
- } else {
36
- const hashedPassword = await bcrypt.hash(password, saltRounds);
37
-
38
- let user = {
39
- id: userid
40
- ,name: name
41
- ,email: email
42
- ,hash: hashedPassword
43
- ,roles: roles
44
- };
45
-
46
- await this.#accessLayer.saveResource(BLCAuth.SYSTEM_USER_ID, user.id, user);
47
-
48
- let payload =
49
- {
50
- id: userid
51
- ,name: name
52
- ,email: email
53
- ,roles: roles
54
- }
55
-
56
- return { status: status.success, detail: payload };
57
- }
58
- } catch (error)
59
- {
60
- console.error(error);
61
- throw new Error({ status: status.error, error: 'Operation was not successful', detail: error });
62
- }
63
- }
64
-
65
- async AddRolePermissions(rolePermissions)
66
- {
67
- try
68
- {
69
- const { name, permissions } = rolePermissions;
70
- let roleId = BLCAuth.ROLE_ID_PREFIX + name;
71
- if (await this.#ResourceExists('Role', roleId)) {
72
- return {
73
- status: status.conflict,
74
- error: 'Role already exists.',
75
- detail: { message: `Role already exists: [${roleId}]` }
76
- };
77
- } else {
78
- let roleResource = {
79
- id: roleId,
80
- name: name,
81
- permissions: permissions
82
- }
83
-
84
- await this.#accessLayer.saveResource(BLCAuth.SYSTEM_USER_ID, roleId, roleResource);
85
-
86
- return { status: status.success, detail: roleResource };
87
- }
88
- } catch (error)
89
- {
90
- console.error(error);
91
- throw new Error({ status: status.error, error: 'Operation was not successful', detail: error });
92
- }
93
- }
94
-
95
- async #GetResource(resource, resourceId) {
96
- let resourceRaw = null;
97
- try {
98
- resourceRaw = await this.#accessLayer.getLatestResource(resourceId);
99
- } catch (error) {
100
- throw new STSDatabaseAccessError(resource, resourceId, error);
101
- }
102
- if (resourceRaw.status !== 200) {
103
- throw new STSResourceNotFoundError(resource, resourceId);
104
- }
105
- try {
106
- return JSON.parse(resourceRaw.detail.resdesc);
107
- } catch (error) {
108
- throw new STSResourceMalformedError(resource, resourceId, resourceRaw.detail.resdesc, error);
109
- }
110
- }
111
-
112
- async #ResourceExists(resource, resourceId) {
113
- try {
114
- await this.#GetResource(resource, resourceId);
115
- return true;
116
- } catch (error) {
117
- if (error instanceof STSResourceNotFoundError) {
118
- return false;
119
- } else {
120
- throw error;
121
- }
122
- }
123
- }
124
-
125
- async GetUser(email) {
126
- return this.#GetResource('User', BLCAuth.USER_ID_PREFIX + email);
127
- }
128
-
129
- async GetRole(role) {
130
- return this.#GetResource('Role', BLCAuth.ROLE_ID_PREFIX + role);
131
- }
132
-
133
- async GetApplication(application) {
134
- return this.#GetResource('Application', BLCAuth.APPLICATION_ID_PREFIX + application);
135
- }
136
-
137
- async GetAPI(identifier) {
138
- return this.#GetResource('API', BLCAuth.API_ID_PREFIX + identifier);
139
- }
140
-
141
- async GetUserPermissions(email)
142
- {
143
- try
144
- {
145
- let userResource = await this.GetUser(email);
146
- let permissions = [ ];
147
-
148
- for (let i=0; i < userResource.roles.length; i++) {
149
- let role = userResource.roles[i];
150
- let roleResource = await this.GetRole(role);
151
- for (let j=0; j < roleResource.permissions.length; j++) {
152
- let permission = roleResource.permissions[j];
153
- if (!permissions.includes(permission)) {
154
- permissions.push(permission);
155
- }
156
- }
157
- }
158
-
159
- return { status: status.success, detail: permissions };
160
- } catch (error)
161
- {
162
- console.error(error);
163
- throw new Error({ status: status.error, error: 'Operation was not successful', detail: error });
164
- }
165
- }
166
-
167
- async AddApplication(application)
168
- {
169
- try
170
- {
171
- const { clientId } = application;
172
- let applicationId = BLCAuth.APPLICATION_ID_PREFIX + clientId;
173
- if (await this.#ResourceExists('Application', applicationId)) {
174
- return {
175
- status: status.conflict,
176
- error: 'Application already exists.',
177
- detail: { message: `Application already exists: [${applicationId}]` }
178
- };
179
- } else {
180
- let payload = {
181
- applicationId,
182
- ...application
183
- }
184
-
185
- await this.#accessLayer.saveResource(BLCAuth.SYSTEM_USER_ID, applicationId, payload);
186
-
187
- // Client Secret is not returned. Seperate function used to display this field.
188
- delete payload.clientSecret;
189
-
190
- return { status: status.success, detail: payload };
191
- }
192
- } catch (error)
193
- {
194
- console.error(error);
195
- throw new Error({ status: status.error, error: 'Operation was not successful', detail: error });
196
- }
197
- }
198
-
199
- #ValidateApplication = async (apiPermissions, app) => {
200
- const { clientId, clientName, permissions } = app;
201
-
202
- let applicationResource = null;
203
- try {
204
- applicationResource = await this.GetApplication(clientId)
205
- } catch (error) {
206
- return { status: status.notfound , error: 'Cannot find client application.', detail: { message: error.message }};
207
- }
208
- if (applicationResource.clientName.localeCompare(clientName) !== 0) {
209
- return { status: status.error, error: 'clientName mismatch.', detail: { message: `clientName mismatch: Value: [${clientName}], Expecting: [${applicationResource.clientName}]` }};
210
- }
211
- for (let j=0; j < permissions.length; j++) {
212
- const permission = permissions[j];
213
- if (!apiPermissions.includes(permission)) {
214
- return { status: status.error, error: `M2M permission not found within API available permission list.`, detail: { message: `Permission not found within API: [${clientName}:${clientId}] available permission list: [${permission}]` }};
215
- }
216
- }
217
- return null;
218
- }
219
-
220
- async AddAPI(api)
221
- {
222
- try
223
- {
224
- const { M2MApplications, permissions: apiPermissions, identifier, SPA } = api;
225
-
226
- let APIidentifier = BLCAuth.API_ID_PREFIX + identifier;
227
-
228
- if (await this.#ResourceExists('API', APIidentifier)) {
229
- return {
230
- status: status.conflict,
231
- error: 'API already exists.',
232
- detail: { message: `API already exists: [${APIidentifier}]` }
233
- };
234
- } else {
235
- // Validate M2MApplications
236
- if (M2MApplications) {
237
- for (let i=0; i < M2MApplications.length; i++) {
238
- let retVal = await this.#ValidateApplication(apiPermissions, M2MApplications[i]);
239
- if (retVal !== null) {
240
- return retVal;
241
- }
242
- }
243
- }
244
-
245
- // Validate SPA
246
- if (SPA) {
247
- for (let i=0; i < SPA.length; i++) {
248
- let retVal = await this.#ValidateApplication(apiPermissions, SPA[i]);
249
- if (retVal !== null) {
250
- return retVal;
251
- }
252
- }
253
- }
254
-
255
- // Client Secret is not returned. Separate function used to display this field.
256
- let payload =
257
- {
258
- APIidentifier,
259
- ...api
260
- }
261
-
262
- await this.#accessLayer.saveResource(BLCAuth.SYSTEM_USER_ID, APIidentifier, payload);
263
-
264
- return { status: status.success, detail: payload };
265
- }
266
- } catch (error)
267
- {
268
- console.error(error);
269
- throw new Error({ status: status.error, error: 'Operation was not successful', detail: error });
270
- }
271
- }
272
-
273
- GetResourcesFromPermissions = (permissions) => {
274
- let sep = '';
275
- let resource = '';
276
- let resourcesArr = [ ];
277
- let resources = '';
278
- let scopes = '';
279
- permissions.forEach(permission => {
280
- scopes += sep + permission;
281
- sep = ' ';
282
- let resourceParts = permission.split('.');
283
- if (resourceParts.length !== 2) {
284
- throw new STSResourceMalformedError('permission', 'N/A', permission);
285
- }
286
- resource = resourceParts[0];
287
- if (!resourcesArr.includes(resource)) {
288
- resourcesArr.push(resource);
289
- }
290
- });
291
- if (resourcesArr.length !== 0) {
292
- resources = resourcesArr.join(' ');
293
- }
294
- return {
295
- scopes,
296
- resources
297
- }
298
- }
299
-
300
- #GetResourcesForApplication = (clientId, audience, app) => {
301
- const permissions = app.permissions;
302
- let sep = '';
303
- let resource = '';
304
- let scopes = '';
305
- let resourcesArr = [ ];
306
- permissions.forEach(permission => {
307
- scopes += sep + permission;
308
- sep = ' ';
309
- let resourceParts = permission.split('.');
310
- if (resourceParts.length !== 2) {
311
- throw new STSResourceMalformedError(app, app.clientId, permission, null, { clientId, audience });
312
- }
313
- resource = resourceParts[0];
314
- if (!resourcesArr.includes(resource)) {
315
- resourcesArr.push(resource);
316
- }
317
- });
318
- if (resourcesArr.length === 0) {
319
- throw new STSNotAuthorized(clientId, audience);
320
- }
321
- const resources = resourcesArr.join(' ');
322
- return {
323
- scopes,
324
- resources
325
- }
326
- }
327
-
328
- // Get all the scopes (permissions) defined for this application (client_id) using this API (audience).
329
- // client_secret required for M2M applications. Not required for SPA.
330
- GetScopes = async (clientId, clientSecret, audience) => {
331
- let applicationResource = await this.GetApplication(clientId);
332
-
333
- if (applicationResource.clientSecret.localeCompare(clientSecret) !== 0) {
334
- throw new STSInvalidCredentials('Application', clientId);
335
- }
336
-
337
- // Get all permissions that have been provided for this client (client_id) using the specified API (audience).
338
- let apiResource = await this.GetAPI(audience);
339
- const { M2MApplications, SPA } = apiResource;
340
-
341
- // Check for M2M applications.
342
- if (M2MApplications) {
343
- for (let i=0; i < M2MApplications.length; i++) {
344
- let m2mApplication = M2MApplications[i];
345
- if (m2mApplication.clientId.localeCompare(clientId) === 0) {
346
- return this.#GetResourcesForApplication(clientId, audience, m2mApplication);
347
- }
348
- }
349
- }
350
-
351
- // Check for SPA (single page applications).
352
- if (SPA) {
353
- for (let i=0; i < SPA.length; i++) {
354
- let spaApplication = SPA[i];
355
- if (spaApplication.clientId.localeCompare(clientId) === 0) {
356
- return this.#GetResourcesForApplication(clientId, audience, spaApplication);
357
- }
358
- }
359
- }
360
-
361
- // client id not authorized for this API (i.e. no permissions for this client app have been created to access this API).
362
- throw new STSNotAuthorized(clientId, audience);
363
- }
364
-
365
- GetAPIsForClientId = async (clientId) => {
366
- console.log(clientId);
367
- let result = await this.#accessLayer.getResources(`${BLCAuth.API_ID_PREFIX}%`);
368
- console.log(result);
369
- }
370
- /*
371
-
372
- // Get all the scopes that the user (user_id) has previously consented for this application (client_id) using this API (audience).
373
- async GetConsentedScopes(user_id, client_id, audience) {
374
-
375
- }
376
-
377
- // Update scopes that the user (user_id) has consented for this application (client_id) using this API (audience).
378
- async UpdateConsentedScopes(user_id, client_id, audience, scopes) {
379
-
380
- }
381
- */
382
-
383
-
384
-
385
-
386
- }
387
-
388
- module.exports = { BLCAuth };