backend-plus 2.0.0-beta.11 → 2.0.0-beta.12

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.
@@ -163,6 +163,7 @@ AppBackend.prototype.configStaticConfig = function configStaticConfig(){
163
163
  skins:
164
164
  "":
165
165
  local-path: for-client
166
+ bin: {}
166
167
  client-setup:
167
168
  skin: ""
168
169
  lang: en
@@ -237,6 +238,9 @@ AppBackend.prototype.i18n.messages.en={
237
238
  },
238
239
  server:{
239
240
  backupNotAvailable: 'Backup not available',
241
+ backupReady: 'Backup ready to download',
242
+ backupZipping: 'Zipping backup file',
243
+ badBackupEncryptKey: 'encrypt key not present or less than 10 characters',
240
244
  cantDelete_TLDR:'Can\'t delete. May be rights problems, locked records or internal problems',
241
245
  cantInsert_TLDR:'Can\'t insert. May be rights problems, locked records or internal problems',
242
246
  cantUpdate_TLDR:'Can\'t update. May be rights problems, locked records or internal problems',
@@ -316,6 +320,9 @@ AppBackend.prototype.i18n.messages.es={
316
320
  },
317
321
  server:{
318
322
  backupNotAvailable: 'Backup no disponible',
323
+ backupReady: 'Archivo listo para bajar',
324
+ backupZipping: 'Compactando el backup',
325
+ badBackupEncryptKey: 'Debe proveer una clave de encriptacion de 10 caracteres o mas para encriptar el archivo de destino',
319
326
  cantDelete_TLDR:'no se pudo eliminar el registro. Podrían haber problemas de persmisos, bloqueo de registros o problemas internos en la definición de la PK',
320
327
  cantInsert_TLDR:'no se pudo insertar el registro. Podrían haber problemas de persmisos, bloqueo de registros o problemas internos en la definición de la PK',
321
328
  cantUpdate_TLDR:'no se pudo modificar el registro. Podrían haber problemas de persmisos, bloqueo de registros o problemas internos en la definición de la PK',
@@ -485,6 +492,12 @@ AppBackend.prototype.isAdmin = function isAdmin(reqOrContext){
485
492
  return reqOrContext && (reqOrContext.forDump || reqOrContext.user && reqOrContext.user[be.config.login.rolFieldName] == 'admin');
486
493
  }
487
494
 
495
+ AppBackend.prototype.can = function can(reqOrContext, what){
496
+ var be = this;
497
+ if (be.isAdmin(reqOrContext)) return true;
498
+ return reqOrContext?.user?.['can' + what];
499
+ }
500
+
488
501
  AppBackend.prototype.canChangePass = async function canChangePass(reqOrContext, _userToChangePass){
489
502
  var be = this;
490
503
  return be.isAdmin(reqOrContext);
@@ -1288,6 +1301,7 @@ AppBackend.prototype.generateInsertSQL = function generateInsertSQL(schemaName,
1288
1301
  }
1289
1302
 
1290
1303
  AppBackend.prototype.updateUpdateSQL = function updateUpdateSQL(schemaName, tableName, updateElement, updateConditions){
1304
+ var be = this;
1291
1305
  var {db} = this;
1292
1306
  var setPairs = [];
1293
1307
  for (var key in updateElement) {
@@ -2383,6 +2397,13 @@ AppBackend.prototype.addLoggedServices = function addLoggedServices(){
2383
2397
  }).catch(MiniTools.serveErr(req,res,next));
2384
2398
  });
2385
2399
  }
2400
+ if(be.config.db['downloadable-backup-path']){
2401
+ be.app.get('/backup-db.zip', function(req,res,next){
2402
+ if (be.can(req, 'DownloadBackup')) {
2403
+ MiniTools.serveFile('./local-private/backup-db.zip')(req,res,next);
2404
+ }
2405
+ })
2406
+ }
2386
2407
  be.app.use(function(req,res,next){
2387
2408
  // req != '/keep-alive.json'
2388
2409
  req.session.lastNonKeepAlive = new Date().getTime();
@@ -4,9 +4,11 @@
4
4
  var {datetime, changing, coalesce} = require('best-globals');
5
5
  var XLSX = require('xlsx');
6
6
  var fs = require('fs/promises')
7
+ var fsSync = require('fs');
7
8
  var typeStore=require('type-store');
8
9
  var likeAr=require('like-ar');
9
10
  const f = require('session-file-store');
11
+ const { expected } = require('cast-error');
10
12
 
11
13
  const PANIC_IMPORT = true;
12
14
 
@@ -1190,7 +1192,7 @@ ProcedureTables = [
1190
1192
  resultOk:'showGrid',
1191
1193
  coreFunction:async function(context,parameters){
1192
1194
  var {be,client} = context;
1193
- if(context.user[be.config.login.rolFieldName] != 'admin'){
1195
+ if(!be.can(context,'SeeHistoryChanges')){
1194
1196
  throw new Error('Forbiden history')
1195
1197
  }
1196
1198
  var tableDef = be.tableStructures[parameters.tableName](context);
@@ -1211,20 +1213,63 @@ ProcedureTables = [
1211
1213
  {
1212
1214
  action:'download_dump',
1213
1215
  parameters:[
1214
- {name:'password' , typeName:'text' },
1216
+ {name:'encrypt', typeName:'text'}
1215
1217
  ],
1216
1218
  bitacora:{always: true, error: true},
1217
1219
  progress:true,
1218
- coreFunction:async function(context,parameters){
1220
+ resultOk:'showDownloadUrl',
1221
+ coreFunction:async function(context, parameters){
1222
+ context.informProgress({message:"tart"});
1219
1223
  var {be,client} = context;
1220
- if(context.user[be.config.login.rolFieldName] != 'admin'){
1221
- throw new Error('Forbiden history')
1224
+ if (!be.can(context,'DownloadBackup')) {
1225
+ throw new Error('Forbiden backup')
1222
1226
  }
1223
- if (!be.config.db['downloadable-backup-path']) {
1227
+ if (parameters.encript?.length < 10) {
1228
+ throw new Error(be.messages.server.badBackupEncryptKey)
1229
+ }
1230
+ var path = be.config.db['downloadable-backup-path']
1231
+ if (!path) {
1224
1232
  throw new Error(be.messages.server.backupNotAvailable)
1225
1233
  }
1226
-
1227
- return result.rows;
1234
+ context.informProgress({message:be.messages.server.backupZipping});
1235
+ var spawn = require('child_process').spawn;
1236
+ try {
1237
+ await fs.mkdir('./local-private');
1238
+ } catch (error) {
1239
+ if (expected(error).code !== 'EEXIST') throw error;
1240
+ try {
1241
+ await fs.unlink('./local-private/backup-db.zip');
1242
+ } catch (error) {
1243
+ if (expected(error).code !== 'ENOENT') throw error;
1244
+ }
1245
+ }
1246
+ var out = fsSync.createWriteStream('./local-private/backup-db.log');
1247
+ await new Promise((resolve, reject) => {
1248
+ out.on('error', reject);
1249
+ out.on('open', resolve);
1250
+ })
1251
+ var zip = spawn(be.config.server.bin.zip ?? 'zip',[
1252
+ ...(be.config.server.bin["zip-fixed-parameters"] ?? []),
1253
+ ...(be.config.server.bin["zip-password-parameter-flag"] === false ? [] : [be.config.server.bin["zip-password-parameter-flag"] ?? '--password']),
1254
+ `${be.config.server.bin["zip-password-prefix"] ?? ''}${parameters.encrypt}` ,
1255
+ './local-private/backup-db.zip',
1256
+ path
1257
+ ], {stdio: [out, out, out]});
1258
+ var code = await new Promise((resolve, reject) => {
1259
+ zip.on('data', chunk => out.write(chunk));
1260
+ zip.on('error', err => {
1261
+ context.informProgress(err);
1262
+ out.end();
1263
+ reject(err);
1264
+ });
1265
+ zip.on('exit', any => {
1266
+ out.end();
1267
+ if (any) reject(new Error("ZIP Error: " + any));
1268
+ resolve(any);
1269
+ });
1270
+ })
1271
+ context.informProgress({message:be.messages.server.backupReady});
1272
+ return [{url: './backup-db.zip', label:'backup-db.zip'}];
1228
1273
  }
1229
1274
  }
1230
1275
  ];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "backend-plus",
3
3
  "description": "Backend for the anti Pareto rule",
4
- "version": "2.0.0-beta.11",
4
+ "version": "2.0.0-beta.12",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/backend-plus",
@@ -54,7 +54,7 @@
54
54
  "mini-tools": "^1.12.1",
55
55
  "moment": "^2.29.4",
56
56
  "multiparty": "^4.2.3",
57
- "nodemailer": "^6.9.5",
57
+ "nodemailer": "^6.9.6",
58
58
  "numeral": "^2.0.6",
59
59
  "pg-promise-strict": "^1.3.3",
60
60
  "pikaday": "^1.8.2",
@@ -73,20 +73,20 @@
73
73
  "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz"
74
74
  },
75
75
  "devDependencies": {
76
- "@types/big.js": "^6.2.0",
77
- "@types/expect.js": "~0.3.30",
78
- "@types/express": "^4.17.18",
79
- "@types/express-useragent": "^1.0.3",
80
- "@types/fs-extra": "^11.0.2",
81
- "@types/js-yaml": "^4.0.6",
82
- "@types/mocha": "^10.0.2",
83
- "@types/multiparty": "~0.0.34",
84
- "@types/node": "^20.8.0",
85
- "@types/nodemailer": "^6.4.11",
86
- "@types/numeral": "~2.0.3",
87
- "@types/session-file-store": "^1.2.3",
88
- "@types/stack-trace": "~0.0.31",
89
- "@types/websql": "~0.0.28",
76
+ "@types/big.js": "^6.2.1",
77
+ "@types/expect.js": "~0.3.31",
78
+ "@types/express": "^4.17.20",
79
+ "@types/express-useragent": "^1.0.4",
80
+ "@types/fs-extra": "^11.0.3",
81
+ "@types/js-yaml": "^4.0.8",
82
+ "@types/mocha": "^10.0.3",
83
+ "@types/multiparty": "~0.0.35",
84
+ "@types/node": "^20.8.7",
85
+ "@types/nodemailer": "^6.4.13",
86
+ "@types/numeral": "~2.0.4",
87
+ "@types/session-file-store": "^1.2.4",
88
+ "@types/stack-trace": "~0.0.32",
89
+ "@types/websql": "~0.0.29",
90
90
  "esprima": "^4.0.1",
91
91
  "expect.js": "~0.3.1",
92
92
  "karma": "6.4.2",
@@ -98,8 +98,8 @@
98
98
  "kill-9": "~0.4.3",
99
99
  "mocha": "^10.2.0",
100
100
  "nyc": "^15.1.0",
101
- "puppeteer": "^21.3.6",
102
- "sinon": "^16.0.0",
101
+ "puppeteer": "^21.4.0",
102
+ "sinon": "^17.0.0",
103
103
  "supertest": "^6.3.3",
104
104
  "types.d.ts": "~0.6.18",
105
105
  "typescript": "^5.2.2",