backend-plus 2.0.0-beta.10 → 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.
@@ -294,9 +294,13 @@ myOwn.TableConnector = function(context, opts){
294
294
  connector.opts = opts||{};
295
295
  connector.fixedFields = connector.opts.fixedFields || [];
296
296
  connector.fixedField = {};
297
+ connector.hideBecauseRelated = {};
297
298
  connector.fixedFields.forEach(function(pair){
298
299
  if(!pair.range && pair.value != myOwn.skipInFixedFields){
299
300
  connector.fixedField[pair.fieldName] = pair.value;
301
+ if (!pair.show) {
302
+ connector.hideBecauseRelated[pair.fieldName] = true;
303
+ }
300
304
  }
301
305
  });
302
306
  connector.parameterFunctions=connector.opts.parameterFunctions||{};
@@ -443,9 +447,13 @@ myOwn.TableConnectorLocal = function(context, opts){
443
447
  connector.opts = opts||{};
444
448
  connector.fixedFields = connector.opts.fixedFields || [];
445
449
  connector.fixedField = {};
450
+ connector.hideBecauseRelated = {};
446
451
  connector.fixedFields.forEach(function(pair){
447
452
  if(!pair.range && pair.value != myOwn.skipInFixedFields){
448
453
  connector.fixedField[pair.fieldName] = pair.value;
454
+ if (!pair.show) {
455
+ connector.hideBecauseRelated[pair.fieldName] = true;
456
+ }
449
457
  }
450
458
  });
451
459
  connector.parameterFunctions=connector.opts.parameterFunctions||{};
@@ -624,19 +632,27 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
624
632
  var primaryKeyValuesForDepotRow = getPrimaryKeyValues(primaryKey, depot.row);
625
633
  return sameValue(JSON.stringify(primaryKeyValuesForRow),JSON.stringify(primaryKeyValuesForDepotRow))
626
634
  });
635
+ if (!depot) {
636
+ var depot = grid.createDepotFromRow(row);
637
+ var needToAddInGrid = true;
638
+ }
639
+ var needToDisplayDepot = !!grid.filterDepots([depot])[0];
640
+ if (!needToDisplayDepot) return;
627
641
  //chequeo que exista depot por las dudas
628
642
  if ((!depot || !depot.tr || !depot.tr.parentNode) && !thereIsANewRecord && !grid.vertical) {
629
- if (!depot) {
643
+ var depotsToDisplay = grid.filterDepots(grid.depots);
644
+ if (needToAddInGrid) {
630
645
  var depot = grid.createDepotFromRow(row);
631
646
  grid.depots.push(depot);
632
- grid.sortDepotsToDisplay(grid.depots);
647
+ var depotsToDisplay = grid.filterDepots(grid.depots);
648
+ grid.sortDepotsToDisplay(depotsToDisplay);
633
649
  } else if (depot.tr && !depot.tr.parentNode) {
634
650
  depot.tr = null
635
651
  }
636
652
  var iRow = -1;
637
653
  var i = 0;
638
- while (i < grid.depots.length){
639
- var aDepot = grid.depots[i];
654
+ while (i < depotsToDisplay.length){
655
+ var aDepot = depotsToDisplay[i];
640
656
  if (depot == aDepot) break;
641
657
  if (aDepot && aDepot.tr && aDepot.tr.parentNode && aDepot.tr.rowIndex != null) {
642
658
  iRow = aDepot.tr.sectionRowIndex
@@ -664,7 +680,8 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
664
680
  })
665
681
  if(!thereIsANewRecord){
666
682
  var i = 0;
667
- var depotsToDelete = grid.depots.filter(depot => depot.tick != tick);
683
+ var depotsToDisplay = grid.filterDepots(grid.depots);
684
+ var depotsToDelete = depotsToDisplay.filter(depot => depot.tick != tick);
668
685
  var depot;
669
686
  if (myOwn.config.config['grid-row-retain-moved-or-deleted'] && !force) {
670
687
  var depotsToRetain = grid.depots.filter(depot => depot.tick == tick);
@@ -921,11 +938,11 @@ myOwn.DataColumnGrid.prototype.cellAttributes = function cellAttributes(specific
921
938
  attr["my-mandatory"]="normal";
922
939
  }
923
940
  }
924
- if(grid.connector.fixedField[fieldDef.name] != null){
941
+ if(grid.connector.hideBecauseRelated[fieldDef.name] && !fieldDef.alwaysShow){
925
942
  attr["inherited-pk-column"]="yes";
926
943
  }
927
944
  if(fieldDef.referencesField){
928
- if(grid.connector.fixedField[fieldDef.referencesField] != null){
945
+ if(grid.connector.hideBecauseRelated[fieldDef.referencesField] && !fieldDef.alwaysShow){
929
946
  attr["inherited-pk-column"]="yes";
930
947
  }
931
948
  if(grid.def.field[fieldDef.referencesField].isPk){
@@ -2605,18 +2622,19 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2605
2622
  }
2606
2623
  return depot;
2607
2624
  };
2608
- grid.displayBody=function displayBody(){
2625
+ grid.filterDepots = function filterDepots(depotsToFilter){
2609
2626
  var grid = this;
2610
- var depotsToDisplay;
2611
2627
  var filterRows = grid.view.filter;
2628
+ var depotsToDisplay;
2612
2629
  if(filterRows && filterRows.length){
2613
- depotsToDisplay = grid.depots.filter(function(depot,i){
2630
+ depotsToDisplay = depotsToFilter.filter(function(depot,i){
2614
2631
  var iFilter=0;
2615
2632
  while(iFilter<filterRows.length){
2616
2633
  var filterData=filterRows[iFilter];
2617
2634
  var partialOk=true;
2618
2635
  var columnsCompared = 0;
2619
2636
  for(var column in depot.row){
2637
+ // var compSymb = filterData.rowSymbols && filterData.rowSymbols[column] || filterData[column].operator;
2620
2638
  var compSymb = filterData.rowSymbols[column];
2621
2639
  if(compSymb && my.comparator[compSymb] && (my.comparatorParameterNull[compSymb] || filterData.row[column] != null)){
2622
2640
  var isSatisfied=my.comparator[compSymb](depot.row[column],filterData.row[column]);
@@ -2634,8 +2652,13 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2634
2652
  return false;
2635
2653
  });
2636
2654
  }else{
2637
- depotsToDisplay = grid.depots;
2655
+ depotsToDisplay = depotsToFilter;
2638
2656
  }
2657
+ return depotsToDisplay;
2658
+ }
2659
+ grid.displayBody=function displayBody(){
2660
+ var grid = this;
2661
+ var depotsToDisplay = grid.filterDepots(grid.depots);
2639
2662
  grid.sortDepotsToDisplay = function sortDepotsToDisplay(depotsToDisplay){
2640
2663
  if(grid.view.sortColumns.length>0){
2641
2664
  return depotsToDisplay.sort(function(depot1, depot2){
@@ -120,7 +120,7 @@ export type MenuInfoMenu = {
120
120
  export type MenuInfoTable = {
121
121
  menuType:'table'
122
122
  table?:string
123
- ff?:{fieldName:string, value:any}[]
123
+ ff?:{fieldName:string, value:any, show?:boolean}[]
124
124
  fc?:{fieldName:string, operator:string, value:any}[]
125
125
  pf?:any
126
126
  td?:TableDefinition
@@ -211,6 +211,7 @@ export type FieldDefinition = EditableDbDefinition & {
211
211
  table?:string
212
212
  inherited?:boolean
213
213
  nameForUpsert?:string
214
+ alwaysShow?:boolean /* show when appears in fixed fields */
214
215
  } & ({} | {
215
216
  sequence:SequenceDefinition
216
217
  nullable:true
@@ -419,6 +420,7 @@ export class AppBackend{
419
420
  messages:Record<LangId,Record<string, string>>
420
421
  }
421
422
  shootDownBackend():Promise<void>
423
+ setLog(opts:{until:string, results?:boolean})
422
424
  }
423
425
 
424
426
  }
@@ -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
@@ -235,7 +236,11 @@ AppBackend.prototype.i18n.messages.en={
235
236
  fileUploaded:'file uploaded',
236
237
  unkownExt:'unkown file extension'
237
238
  },
238
- server:{
239
+ server:{
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',
239
244
  cantDelete_TLDR:'Can\'t delete. May be rights problems, locked records or internal problems',
240
245
  cantInsert_TLDR:'Can\'t insert. May be rights problems, locked records or internal problems',
241
246
  cantUpdate_TLDR:'Can\'t update. May be rights problems, locked records or internal problems',
@@ -314,6 +319,10 @@ AppBackend.prototype.i18n.messages.es={
314
319
  unkownExt:'extensión de archivo desconocida'
315
320
  },
316
321
  server:{
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',
317
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',
318
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',
319
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',
@@ -483,6 +492,12 @@ AppBackend.prototype.isAdmin = function isAdmin(reqOrContext){
483
492
  return reqOrContext && (reqOrContext.forDump || reqOrContext.user && reqOrContext.user[be.config.login.rolFieldName] == 'admin');
484
493
  }
485
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
+
486
501
  AppBackend.prototype.canChangePass = async function canChangePass(reqOrContext, _userToChangePass){
487
502
  var be = this;
488
503
  return be.isAdmin(reqOrContext);
@@ -1286,6 +1301,7 @@ AppBackend.prototype.generateInsertSQL = function generateInsertSQL(schemaName,
1286
1301
  }
1287
1302
 
1288
1303
  AppBackend.prototype.updateUpdateSQL = function updateUpdateSQL(schemaName, tableName, updateElement, updateConditions){
1304
+ var be = this;
1289
1305
  var {db} = this;
1290
1306
  var setPairs = [];
1291
1307
  for (var key in updateElement) {
@@ -2381,6 +2397,13 @@ AppBackend.prototype.addLoggedServices = function addLoggedServices(){
2381
2397
  }).catch(MiniTools.serveErr(req,res,next));
2382
2398
  });
2383
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
+ }
2384
2407
  be.app.use(function(req,res,next){
2385
2408
  // req != '/keep-alive.json'
2386
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);
@@ -1207,6 +1209,68 @@ ProcedureTables = [
1207
1209
  `,[parameters.tableName, parameters.fieldName]).fetchAll();
1208
1210
  return result.rows;
1209
1211
  }
1212
+ },
1213
+ {
1214
+ action:'download_dump',
1215
+ parameters:[
1216
+ {name:'encrypt', typeName:'text'}
1217
+ ],
1218
+ bitacora:{always: true, error: true},
1219
+ progress:true,
1220
+ resultOk:'showDownloadUrl',
1221
+ coreFunction:async function(context, parameters){
1222
+ context.informProgress({message:"tart"});
1223
+ var {be,client} = context;
1224
+ if (!be.can(context,'DownloadBackup')) {
1225
+ throw new Error('Forbiden backup')
1226
+ }
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) {
1232
+ throw new Error(be.messages.server.backupNotAvailable)
1233
+ }
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'}];
1273
+ }
1210
1274
  }
1211
1275
  ];
1212
1276
 
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.10",
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.4",
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",
@@ -67,26 +67,26 @@
67
67
  "session-file-store": "^1.5.0",
68
68
  "sql-tools": "^0.1.2",
69
69
  "stack-trace": "^0.0.10",
70
- "stylus": "0.59.0",
70
+ "stylus": "0.60.0",
71
71
  "type-store": "^0.4.0",
72
72
  "typed-controls": "^0.12.0",
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.29",
78
- "@types/express": "^4.17.17",
79
- "@types/express-useragent": "^1.0.2",
80
- "@types/fs-extra": "^11.0.1",
81
- "@types/js-yaml": "^4.0.5",
82
- "@types/mocha": "^10.0.1",
83
- "@types/multiparty": "~0.0.33",
84
- "@types/node": "^20.5.1",
85
- "@types/nodemailer": "^6.4.9",
86
- "@types/numeral": "~2.0.2",
87
- "@types/session-file-store": "^1.2.2",
88
- "@types/stack-trace": "~0.0.30",
89
- "@types/websql": "~0.0.27",
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,11 +98,11 @@
98
98
  "kill-9": "~0.4.3",
99
99
  "mocha": "^10.2.0",
100
100
  "nyc": "^15.1.0",
101
- "puppeteer": "^21.1.0",
102
- "sinon": "^15.2.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
- "typescript": "^5.1.6",
105
+ "typescript": "^5.2.2",
106
106
  "why-is-node-running": "^2.2.2"
107
107
  },
108
108
  "engines": {