backend-plus 2.7.0-beta.2 → 2.7.0-beta.4
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/for-client/css/my-things.styl +11 -0
- package/lib/backend-plus.d.ts +1 -1
- package/lib/backend-plus.js +117 -112
- package/package.json +17 -16
package/lib/backend-plus.d.ts
CHANGED
|
@@ -169,7 +169,7 @@ export interface TableContext extends Context{
|
|
|
169
169
|
superuser?:true
|
|
170
170
|
forDump?:boolean
|
|
171
171
|
}
|
|
172
|
-
export type PgKnownTypes='decimal'|'text'|'boolean'|'integer'|'bigint'|'date'|'interval'|'timestamp'|'jsonb'|'double'|'bytea'|'jsona'|'time'|'tsrange'|'time_range'|'daterange'|'time_multirange';
|
|
172
|
+
export type PgKnownTypes='decimal'|'text'|'boolean'|'integer'|'bigint'|'date'|'interval'|'timestamp'|'jsonb'|'double'|'bytea'|'jsona'|'time'|'tsrange'|'time_range'|'daterange'|'time_multirange'|'gpoint'|'point';
|
|
173
173
|
export type PgKnownDbValues='current_timestamp'|'current_user'|'session_user';
|
|
174
174
|
export type SequenceDefinition = {
|
|
175
175
|
name:string
|
package/lib/backend-plus.js
CHANGED
|
@@ -73,7 +73,7 @@ if(dashDashDir>0){
|
|
|
73
73
|
console.log('cwd',process.cwd());
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
/**
|
|
76
|
+
/**
|
|
77
77
|
* @param {string} text
|
|
78
78
|
* @return {string}
|
|
79
79
|
*/
|
|
@@ -81,14 +81,14 @@ function md5(text){
|
|
|
81
81
|
return crypto.createHash('md5').update(text).digest('hex');
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const DEFAULT_ITERATIONS = 4096;
|
|
84
|
+
const DEFAULT_ITERATIONS = 4096;
|
|
85
85
|
const HASH_ALGORITHM = 'sha256';
|
|
86
86
|
|
|
87
87
|
// primera version de scram sha 256. El Verifier completo tenía 64 bytes.
|
|
88
|
-
const LEGACY_KEY_LENGTH = 64;
|
|
88
|
+
const LEGACY_KEY_LENGTH = 64;
|
|
89
89
|
|
|
90
90
|
// Formato nuevo/PG-Compatible: El Client Key tiene 32 bytes (SHA-256).
|
|
91
|
-
const SCRAM_KEY_LENGTH = 32;
|
|
91
|
+
const SCRAM_KEY_LENGTH = 32;
|
|
92
92
|
|
|
93
93
|
const bufferToBase64 = (buffer) => buffer.toString('base64');
|
|
94
94
|
|
|
@@ -96,31 +96,31 @@ const bufferToBase64 = (buffer) => buffer.toString('base64');
|
|
|
96
96
|
* Función central para PBKDF2 (Acepta KEY_LEN para compatibilidad).
|
|
97
97
|
* Devuelve la clave derivada con la longitud especificada.
|
|
98
98
|
*/
|
|
99
|
-
async function deriveKey(password, saltBuffer, iterations, keyLength) {
|
|
99
|
+
async function deriveKey(password, saltBuffer, iterations, keyLength) {
|
|
100
100
|
return new Promise((resolve, reject) => {
|
|
101
101
|
crypto.pbkdf2(
|
|
102
|
-
password,
|
|
102
|
+
password,
|
|
103
103
|
saltBuffer,
|
|
104
|
-
iterations,
|
|
104
|
+
iterations,
|
|
105
105
|
keyLength,
|
|
106
|
-
HASH_ALGORITHM,
|
|
106
|
+
HASH_ALGORITHM,
|
|
107
107
|
(err, derivedKey) => {
|
|
108
108
|
if (err) return reject(err);
|
|
109
|
-
resolve(derivedKey);
|
|
109
|
+
resolve(derivedKey);
|
|
110
110
|
}
|
|
111
111
|
);
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
async function generateScramVerifier(password) {
|
|
116
|
-
const saltBuffer = crypto.randomBytes(16);
|
|
116
|
+
const saltBuffer = crypto.randomBytes(16);
|
|
117
117
|
const saltBase64 = bufferToBase64(saltBuffer);
|
|
118
118
|
|
|
119
119
|
const Hi = await deriveKey(
|
|
120
|
-
password,
|
|
121
|
-
saltBuffer,
|
|
120
|
+
password,
|
|
121
|
+
saltBuffer,
|
|
122
122
|
DEFAULT_ITERATIONS,
|
|
123
|
-
SCRAM_KEY_LENGTH
|
|
123
|
+
SCRAM_KEY_LENGTH
|
|
124
124
|
);
|
|
125
125
|
const clientKey = crypto.createHmac('sha256', Hi).update('Client Key').digest();
|
|
126
126
|
const serverKey = crypto.createHmac('sha256', Hi).update('Server Key').digest();
|
|
@@ -144,27 +144,27 @@ async function verifyScramPG(password, storedScramString) {
|
|
|
144
144
|
if (!storedScramString.startsWith('SCRAM-SHA-256$')) {
|
|
145
145
|
return false;
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
|
|
148
148
|
const parts = storedScramString.split('$');
|
|
149
149
|
if (parts.length !== 3) {
|
|
150
150
|
return false;
|
|
151
151
|
}
|
|
152
|
-
|
|
152
|
+
|
|
153
153
|
const [storedIterations, saltBase64] = parts[1].split(':');
|
|
154
154
|
const [storedKeyBase64, serverKeyBase64] = parts[2].split(':'); // Asume StoredKey y ServerKey
|
|
155
155
|
|
|
156
156
|
if (!saltBase64 || !storedKeyBase64 || !serverKeyBase64 || isNaN(parseInt(storedIterations))) {
|
|
157
157
|
return false;
|
|
158
158
|
}
|
|
159
|
-
|
|
159
|
+
|
|
160
160
|
const iterations = parseInt(storedIterations);
|
|
161
161
|
const saltBuffer = Buffer.from(saltBase64, 'base64');
|
|
162
162
|
const storedKeyBuffer = Buffer.from(storedKeyBase64, 'base64');
|
|
163
163
|
const serverKeyBuffer = Buffer.from(serverKeyBase64, 'base64');
|
|
164
164
|
|
|
165
165
|
const Hi = await deriveKey(
|
|
166
|
-
password,
|
|
167
|
-
saltBuffer,
|
|
166
|
+
password,
|
|
167
|
+
saltBuffer,
|
|
168
168
|
iterations,
|
|
169
169
|
SCRAM_KEY_LENGTH
|
|
170
170
|
);
|
|
@@ -203,21 +203,21 @@ async function verifyScramLegacy(password, storedScramString) {
|
|
|
203
203
|
if (parts.length !== 3) {
|
|
204
204
|
throw new Error('Formato SCRAM almacenado inválido.');
|
|
205
205
|
}
|
|
206
|
-
|
|
206
|
+
|
|
207
207
|
// Obtiene iteraciones y salt de la segunda parte (ej: '4096:SALT_BASE64')
|
|
208
208
|
const [storedIterations, storedSalt] = parts[1].split(':');
|
|
209
209
|
const storedVerifier = parts[2];
|
|
210
|
-
|
|
210
|
+
|
|
211
211
|
if (!storedSalt || !storedVerifier || isNaN(parseInt(storedIterations))) {
|
|
212
212
|
throw new Error('Datos de SCRAM incompletos o malformados.');
|
|
213
213
|
}
|
|
214
|
-
|
|
214
|
+
|
|
215
215
|
const iterations = parseInt(storedIterations);
|
|
216
216
|
|
|
217
217
|
// Deriva la clave de la contraseña ingresada
|
|
218
218
|
const generatedVerifierBuffer = await deriveKey(
|
|
219
|
-
password,
|
|
220
|
-
storedSalt,
|
|
219
|
+
password,
|
|
220
|
+
storedSalt,
|
|
221
221
|
iterations,
|
|
222
222
|
LEGACY_KEY_LENGTH
|
|
223
223
|
);
|
|
@@ -313,7 +313,7 @@ AppBackend.prototype.configStaticConfig = function configStaticConfig(){
|
|
|
313
313
|
min-version: 12
|
|
314
314
|
fkOnUpdate: cascade
|
|
315
315
|
max: 50
|
|
316
|
-
log:
|
|
316
|
+
log:
|
|
317
317
|
db:
|
|
318
318
|
until: 2001-01-01 00:00
|
|
319
319
|
last-error: false
|
|
@@ -326,7 +326,7 @@ AppBackend.prototype.configStaticConfig = function configStaticConfig(){
|
|
|
326
326
|
"":
|
|
327
327
|
local-path: for-client
|
|
328
328
|
bin: {}
|
|
329
|
-
client-setup:
|
|
329
|
+
client-setup:
|
|
330
330
|
skin: ""
|
|
331
331
|
lang: en
|
|
332
332
|
version: 1.0
|
|
@@ -589,7 +589,7 @@ function MemoryPerodicallySaved(session){
|
|
|
589
589
|
})}
|
|
590
590
|
|
|
591
591
|
/**
|
|
592
|
-
* @param {string} text
|
|
592
|
+
* @param {string} text
|
|
593
593
|
*/
|
|
594
594
|
AppBackend.prototype.jsonPass = function jsonPass(text){
|
|
595
595
|
return JSON.stringify(text,null,' ').replace(/\n(.*".*(pass|clave|secret).*":\s*").*(",?)\n/gi,'\n$1********$3\n');
|
|
@@ -751,7 +751,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
751
751
|
while(iPosDbDump && iPosDbDump<process.argv.length && !process.argv[iPosDbDump].startsWith('--')){
|
|
752
752
|
dumps.push(process.argv[iPosDbDump]);
|
|
753
753
|
iPosDbDump++;
|
|
754
|
-
}
|
|
754
|
+
}
|
|
755
755
|
opts["dump-db"]={
|
|
756
756
|
complete:!dumps.length,
|
|
757
757
|
tableNames:dumps instanceof Array?dumps:null,
|
|
@@ -888,8 +888,8 @@ AppBackend.prototype.start = function start(opts){
|
|
|
888
888
|
}
|
|
889
889
|
be.db = pg;
|
|
890
890
|
be.dbUserNameExpr="get_app_user()";
|
|
891
|
-
be.dbUserRolExpr=`(select ${be.db.quoteIdent(be.config.login.rolFieldName)}
|
|
892
|
-
from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.db.quoteIdent(be.config.login.table)}
|
|
891
|
+
be.dbUserRolExpr=`(select ${be.db.quoteIdent(be.config.login.rolFieldName)}
|
|
892
|
+
from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.db.quoteIdent(be.config.login.table)}
|
|
893
893
|
where ${be.db.quoteIdent(be.config.login.userFieldName)} = ${be.dbUserNameExpr})`
|
|
894
894
|
}).then(function(){
|
|
895
895
|
if(opts["dump-db"]){
|
|
@@ -1032,6 +1032,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1032
1032
|
console.log(err);
|
|
1033
1033
|
throw err;
|
|
1034
1034
|
}
|
|
1035
|
+
await pg.setAllTypes(client);
|
|
1035
1036
|
var data = await client.query("SELECT current_timestamp as cts").fetchUniqueRow();
|
|
1036
1037
|
if(verboseStartup){
|
|
1037
1038
|
console.log('NOW in Database',data.row.cts);
|
|
@@ -1047,7 +1048,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1047
1048
|
},function(){ /*OK, login.jade must not be here */ }),
|
|
1048
1049
|
fs.stat('client/login.jade').then(function(){
|
|
1049
1050
|
return Path.resolve(be.rootPath,'client/login');
|
|
1050
|
-
},function(){
|
|
1051
|
+
},function(){
|
|
1051
1052
|
return Path.join(__dirname,'../for-client/login');
|
|
1052
1053
|
}).then(function(loginFile){
|
|
1053
1054
|
be.config.login.plus.loginPageServe=function(req,res,next){
|
|
@@ -1164,7 +1165,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1164
1165
|
if(verboseStartup){
|
|
1165
1166
|
console.log('-------------------');
|
|
1166
1167
|
console.log(
|
|
1167
|
-
'be.config.login',
|
|
1168
|
+
'be.config.login',
|
|
1168
1169
|
be.jsonPass(be.config.login)
|
|
1169
1170
|
);
|
|
1170
1171
|
}
|
|
@@ -1193,7 +1194,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1193
1194
|
}
|
|
1194
1195
|
});
|
|
1195
1196
|
const updatePassword = async ({client, username, password, setUpdateDate, errorIfNoResult}) => {
|
|
1196
|
-
const {table, passFieldName, userFieldName, passUpdatedAtFieldName, passAlgorithmFieldName, schema} = be.config.login;
|
|
1197
|
+
const {table, passFieldName, userFieldName, passUpdatedAtFieldName, passAlgorithmFieldName, schema} = be.config.login;
|
|
1197
1198
|
const hashPass = await generateScramVerifier(password);
|
|
1198
1199
|
let params = [username, hashPass];
|
|
1199
1200
|
let setters = [`${be.db.quoteIdent(passFieldName)} = $2`];
|
|
@@ -1204,9 +1205,9 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1204
1205
|
if(setUpdateDate && passUpdatedAtFieldName){
|
|
1205
1206
|
setters.push(`${be.db.quoteIdent(passUpdatedAtFieldName)} = current_timestamp`)
|
|
1206
1207
|
}
|
|
1207
|
-
|
|
1208
|
+
|
|
1208
1209
|
const result = await client.query(`
|
|
1209
|
-
UPDATE ${(schema ? be.db.quoteIdent(schema) + '.' : '') + be.db.quoteIdent(table)}
|
|
1210
|
+
UPDATE ${(schema ? be.db.quoteIdent(schema) + '.' : '') + be.db.quoteIdent(table)}
|
|
1210
1211
|
SET ${setters.join(', ')}
|
|
1211
1212
|
WHERE ${be.db.quoteIdent(userFieldName)} = $1
|
|
1212
1213
|
returning 1 as ok
|
|
@@ -1236,7 +1237,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1236
1237
|
[userFieldName]
|
|
1237
1238
|
)
|
|
1238
1239
|
).concat(passFieldName);
|
|
1239
|
-
|
|
1240
|
+
|
|
1240
1241
|
const sql = "SELECT "+infoFieldList.map(function(fieldOrPair){ return fieldOrPair.split(' as ').map(function(ident){ return be.db.quoteIdent(ident)}).join(' as '); })+
|
|
1241
1242
|
", "+be.config.login.activeClausule+" as active "+
|
|
1242
1243
|
", "+be.config.login.lockedClausule+" as locked "+
|
|
@@ -1264,7 +1265,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1264
1265
|
if(await verifyScramPG(password, user[passFieldName])){
|
|
1265
1266
|
isScramValid = true;
|
|
1266
1267
|
}
|
|
1267
|
-
|
|
1268
|
+
|
|
1268
1269
|
// 2. Intento con formato Legacy (64 bytes)
|
|
1269
1270
|
else if(await verifyScramLegacy(password, user[passFieldName])){
|
|
1270
1271
|
isScramValid = true;
|
|
@@ -1274,7 +1275,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1274
1275
|
done(null,false,{message:be.messages.unlogged.login.userOrPassFail});
|
|
1275
1276
|
return
|
|
1276
1277
|
}
|
|
1277
|
-
}else{
|
|
1278
|
+
}else{
|
|
1278
1279
|
if (md5(password+username.toLowerCase()) === user[passFieldName]){
|
|
1279
1280
|
needsMigration = true;
|
|
1280
1281
|
}else{
|
|
@@ -1288,7 +1289,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1288
1289
|
if (be.config.log["pass-migration"]) console.log('Migración completada.');
|
|
1289
1290
|
}
|
|
1290
1291
|
}
|
|
1291
|
-
//continua validando
|
|
1292
|
+
//continua validando
|
|
1292
1293
|
if(data.rowCount==1){
|
|
1293
1294
|
if(!data.row.active){
|
|
1294
1295
|
done(null,false,{message:be.messages.unlogged.login.inactiveFail});
|
|
@@ -1344,7 +1345,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1344
1345
|
const data = await client.query(
|
|
1345
1346
|
`SELECT *
|
|
1346
1347
|
FROM ${(schema ? be.db.quoteIdent(schema) + '.' : '')}${be.db.quoteIdent(table)}
|
|
1347
|
-
WHERE ${be.db.quoteIdent(userFieldName)} = $1`,
|
|
1348
|
+
WHERE ${be.db.quoteIdent(userFieldName)} = $1`,
|
|
1348
1349
|
[username]
|
|
1349
1350
|
).fetchOneRowIfExists();
|
|
1350
1351
|
if (data.rowCount !== 1) {
|
|
@@ -1360,7 +1361,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1360
1361
|
ok = await verifyScramLegacy(oldPassword, storedHash);
|
|
1361
1362
|
}
|
|
1362
1363
|
} else { //Intento MD5
|
|
1363
|
-
const md5Hash = md5(oldPassword + username.toLowerCase());
|
|
1364
|
+
const md5Hash = md5(oldPassword + username.toLowerCase());
|
|
1364
1365
|
ok = (md5Hash === storedHash);
|
|
1365
1366
|
}
|
|
1366
1367
|
if (!ok) {
|
|
@@ -1454,7 +1455,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1454
1455
|
to: be.config.mailer?.supervise?.to,
|
|
1455
1456
|
subject: `npm start ${be.config["client-setup"]?.title || packagejson.name} ok ✔️`,
|
|
1456
1457
|
text:`Inicio del servicio: ${new Date().toJSON()}
|
|
1457
|
-
|
|
1458
|
+
|
|
1458
1459
|
Contexto: ${os.userInfo().username} ${process.cwd()}
|
|
1459
1460
|
`
|
|
1460
1461
|
}, {ignoreNoMailer:true, event:'restart-ok'})
|
|
@@ -1462,7 +1463,7 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1462
1463
|
if(err.dumping=='ok'){
|
|
1463
1464
|
console.log('db struct dumped');
|
|
1464
1465
|
process.exit(0);
|
|
1465
|
-
return;
|
|
1466
|
+
return;
|
|
1466
1467
|
}
|
|
1467
1468
|
console.log('ERROR',err.stack || err);
|
|
1468
1469
|
if(err.context){
|
|
@@ -1476,11 +1477,11 @@ AppBackend.prototype.start = function start(opts){
|
|
|
1476
1477
|
to: be.config.mailer?.supervise?.to,
|
|
1477
1478
|
subject: `npm start ${be.config["client-setup"]?.title || packagejson.name} fallido 🛑`,
|
|
1478
1479
|
text:`Falla en el inicio del servicio: ${new Date().toJSON()}
|
|
1479
|
-
|
|
1480
|
+
|
|
1480
1481
|
Contexto: ${os.userInfo().username} ${process.cwd()}
|
|
1481
1482
|
|
|
1482
1483
|
Mensaje: ${err.message}
|
|
1483
|
-
|
|
1484
|
+
|
|
1484
1485
|
${err.stack}
|
|
1485
1486
|
`
|
|
1486
1487
|
}, {ignoreNoMailer:true, event:'restart-fail'})
|
|
@@ -1549,7 +1550,7 @@ AppBackend.prototype.checkDatabaseStructure = async function checkDatabaseStruct
|
|
|
1549
1550
|
throw err;
|
|
1550
1551
|
}
|
|
1551
1552
|
try{
|
|
1552
|
-
await client.query(`select ${be.db.quoteIdentList(be.config.login.forget.mailFields)}
|
|
1553
|
+
await client.query(`select ${be.db.quoteIdentList(be.config.login.forget.mailFields)}
|
|
1553
1554
|
from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.config.login.table} limit 1`).fetchOneRowIfExists();
|
|
1554
1555
|
}catch(err){
|
|
1555
1556
|
var mensaje = `
|
|
@@ -1564,7 +1565,7 @@ AppBackend.prototype.checkDatabaseStructure = async function checkDatabaseStruct
|
|
|
1564
1565
|
}
|
|
1565
1566
|
}
|
|
1566
1567
|
var bitacoraTableName = be.config.server.bitacoraTableName || 'bitacora';
|
|
1567
|
-
var bitacoraId = await client.query(`SELECT data_type
|
|
1568
|
+
var bitacoraId = await client.query(`SELECT data_type
|
|
1568
1569
|
FROM information_schema.columns
|
|
1569
1570
|
WHERE /*table_schema = 'his' AND*/ table_name = '${bitacoraTableName}' AND column_name = 'id'
|
|
1570
1571
|
`).fetchOneRowIfExists();
|
|
@@ -1609,9 +1610,9 @@ AppBackend.prototype.postConfig = function postConfig(){
|
|
|
1609
1610
|
AppBackend.prototype.getContext = function getContext(req){
|
|
1610
1611
|
var be = this;
|
|
1611
1612
|
return {
|
|
1612
|
-
be, user:req.user, session:req.session,
|
|
1613
|
-
username:req.user && req.user[be.config.login.userFieldName],
|
|
1614
|
-
machineId:req.machineId,
|
|
1613
|
+
be, user:req.user, session:req.session,
|
|
1614
|
+
username:req.user && req.user[be.config.login.userFieldName],
|
|
1615
|
+
machineId:req.machineId,
|
|
1615
1616
|
navigator:(req.userAgent||{}).shortDescription||'?'
|
|
1616
1617
|
};
|
|
1617
1618
|
}
|
|
@@ -1641,7 +1642,7 @@ AppBackend.prototype.generateInsertSQL = function generateInsertSQL(schemaName,
|
|
|
1641
1642
|
var cleanValues = [];
|
|
1642
1643
|
for (var key in insertElement) {
|
|
1643
1644
|
cleanKeys.push(db.quoteIdent(key));
|
|
1644
|
-
cleanValues.push(db.quoteNullable(insertElement[key]));
|
|
1645
|
+
cleanValues.push(db.quoteNullable(insertElement[key]));
|
|
1645
1646
|
}
|
|
1646
1647
|
var sql = `INSERT INTO ${db.quoteIdent(schemaName)}.${db.quoteIdent(tableName)}
|
|
1647
1648
|
(${cleanKeys.join(',')}) VALUES (${cleanValues.join(',')}) returning id`;
|
|
@@ -1659,7 +1660,7 @@ AppBackend.prototype.updateUpdateSQL = function updateUpdateSQL(schemaName, tabl
|
|
|
1659
1660
|
for (var key in updateConditions) {
|
|
1660
1661
|
filterPairs.push(be.db.quoteIdent(key) + " = " + be.db.quoteLiteral(updateConditions[key]));
|
|
1661
1662
|
};
|
|
1662
|
-
var sql = `UPDATE ${db.quoteIdent(schemaName)}.${db.quoteIdent(tableName)}
|
|
1663
|
+
var sql = `UPDATE ${db.quoteIdent(schemaName)}.${db.quoteIdent(tableName)}
|
|
1663
1664
|
SET ${setPairs.join(',')}
|
|
1664
1665
|
WHERE ${filterPairs.join(' AND ')}`;
|
|
1665
1666
|
return sql;
|
|
@@ -1667,7 +1668,7 @@ AppBackend.prototype.updateUpdateSQL = function updateUpdateSQL(schemaName, tabl
|
|
|
1667
1668
|
|
|
1668
1669
|
|
|
1669
1670
|
/** @param {boolean} forUnlogged */
|
|
1670
|
-
AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnlogged){
|
|
1671
|
+
AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnlogged){
|
|
1671
1672
|
var be = this;
|
|
1672
1673
|
if(forUnlogged){
|
|
1673
1674
|
var app = express();
|
|
@@ -1685,7 +1686,7 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
|
|
|
1685
1686
|
be.procedures = defs;
|
|
1686
1687
|
be.clientSetup.procedure = be.procedure;
|
|
1687
1688
|
app.get('/client-setup',async function(req, res, next){
|
|
1688
|
-
if(forUnlogged && req.user){
|
|
1689
|
+
if(forUnlogged && req.user){
|
|
1689
1690
|
// este pedido es para unlogged y está logueado, va al próximo
|
|
1690
1691
|
next();
|
|
1691
1692
|
}else{
|
|
@@ -1715,12 +1716,12 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
|
|
|
1715
1716
|
if(!isLowerIdent(procedureDef.action)){
|
|
1716
1717
|
console.error('**** DEPRECATED ***** procedureDef action '+JSON.stringify(procedureDef.action)+' must be a Lower Ident');
|
|
1717
1718
|
}
|
|
1718
|
-
app[procedureDef.method]('/'+procedureDef.action,
|
|
1719
|
+
app[procedureDef.method]('/'+procedureDef.action,
|
|
1719
1720
|
/**
|
|
1720
|
-
*
|
|
1721
|
-
* @param {Request} req
|
|
1722
|
-
* @param {Response} res
|
|
1723
|
-
* @param {import('express').NextFunction} next
|
|
1721
|
+
*
|
|
1722
|
+
* @param {Request} req
|
|
1723
|
+
* @param {Response} res
|
|
1724
|
+
* @param {import('express').NextFunction} next
|
|
1724
1725
|
*/
|
|
1725
1726
|
async function(req, res, next){
|
|
1726
1727
|
const BITACORA_SCHEMA = be.config.server.bitacoraSchema;
|
|
@@ -1773,9 +1774,9 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
|
|
|
1773
1774
|
init_date: initDatetimeString,
|
|
1774
1775
|
};
|
|
1775
1776
|
var getFinalStatusBitacoraElement = function getFinalStatusBitacoraElement(){
|
|
1776
|
-
return {
|
|
1777
|
-
end_date: getDatetimeString(),
|
|
1778
|
-
end_status: status,
|
|
1777
|
+
return {
|
|
1778
|
+
end_date: getDatetimeString(),
|
|
1779
|
+
end_status: status,
|
|
1779
1780
|
has_error: hasError
|
|
1780
1781
|
}
|
|
1781
1782
|
}
|
|
@@ -1805,12 +1806,12 @@ AppBackend.prototype.addProcedureServices = function addProcedureServices(forUnl
|
|
|
1805
1806
|
var params = getParams();
|
|
1806
1807
|
if(status){
|
|
1807
1808
|
//terminó ejecucion
|
|
1808
|
-
updateElement[procedureDef.bitacora.targetTableBitacoraFields.end_date] = getDatetimeString();
|
|
1809
|
+
updateElement[procedureDef.bitacora.targetTableBitacoraFields.end_date] = getDatetimeString();
|
|
1809
1810
|
updateElement[procedureDef.bitacora.targetTableBitacoraFields.end_status] = status;
|
|
1810
1811
|
updateElement[procedureDef.bitacora.targetTableBitacoraFields.has_error] = hasError;
|
|
1811
1812
|
}else{
|
|
1812
1813
|
//empezó ejecucion
|
|
1813
|
-
updateElement[procedureDef.bitacora.targetTableBitacoraFields.init_date] = initDatetimeString;
|
|
1814
|
+
updateElement[procedureDef.bitacora.targetTableBitacoraFields.init_date] = initDatetimeString;
|
|
1814
1815
|
}
|
|
1815
1816
|
await be.inTransaction(req,async function(client){
|
|
1816
1817
|
targetTableUpdateFieldsCondition.forEach(function(field){
|
|
@@ -2114,7 +2115,7 @@ AppBackend.prototype.optsGenericForFiles = function optsGenericForFiles(req, opt
|
|
|
2114
2115
|
return changing(be.optsGenericForAll||{},{
|
|
2115
2116
|
allowedExts:be.exts.normal,
|
|
2116
2117
|
jade:{
|
|
2117
|
-
skin:skin,
|
|
2118
|
+
skin:skin,
|
|
2118
2119
|
skinUrl:skinUrl,
|
|
2119
2120
|
formTitle:title,
|
|
2120
2121
|
...(opts?.withFlash ? {flash:req?.flash?.()} : {}),
|
|
@@ -2133,8 +2134,8 @@ AppBackend.prototype.unloggedLandPage = function unloggedLandPage(req){
|
|
|
2133
2134
|
html.h2({style:'text-align:center; margin-top:15%; font-family:arial, sans-serif'},[be.messages.server.notLoggedIn]),
|
|
2134
2135
|
html.h2({style:'text-align:center'},[html.code([
|
|
2135
2136
|
html.a({
|
|
2136
|
-
id:'goto-login',
|
|
2137
|
-
style:'border:0.5px solid blue; border-radius: 6px; padding: 6px',
|
|
2137
|
+
id:'goto-login',
|
|
2138
|
+
style:'border:0.5px solid blue; border-radius: 6px; padding: 6px',
|
|
2138
2139
|
href:Path.posix.join(be.config.server["base-url"],(be.config.login.plus.loginUrlPath||'/login'))
|
|
2139
2140
|
},'login')
|
|
2140
2141
|
])]),
|
|
@@ -2157,8 +2158,8 @@ AppBackend.prototype.addUnloggedServices = function addUnloggedServices(mainApp,
|
|
|
2157
2158
|
var now = bestGlobals.datetime.now();
|
|
2158
2159
|
var token = crypto.randomUUID();
|
|
2159
2160
|
var {rows} = await client.query(`select ${be.db.quoteIdent(be.config.login.userFieldName)} as username
|
|
2160
|
-
from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.db.quoteIdent(be.config.login.table)}
|
|
2161
|
-
where $1 in (${be.db.quoteIdentList(be.config.login.forget.mailFields)})
|
|
2161
|
+
from ${be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':''}${be.db.quoteIdent(be.config.login.table)}
|
|
2162
|
+
where $1 in (${be.db.quoteIdentList(be.config.login.forget.mailFields)})
|
|
2162
2163
|
and ${be.config.login.activeClausule}
|
|
2163
2164
|
and ${be.config.login.lockedClausule} is not true
|
|
2164
2165
|
`, [req.body.email.toLowerCase()]).fetchAll();
|
|
@@ -2266,21 +2267,21 @@ AppBackend.prototype.addUnloggedServices = function addUnloggedServices(mainApp,
|
|
|
2266
2267
|
// http://localhost:3033/img/login-logo-icon.png
|
|
2267
2268
|
mainApp.get(Path.posix.join(baseUrl,'/img/login-logo-icon.png'), async function(req,res,next){
|
|
2268
2269
|
var buscar = [
|
|
2269
|
-
'unlogged/img/login-logo-icon.svg',
|
|
2270
|
-
'dist/unlogged/img/login-logo-icon.svg',
|
|
2271
|
-
'dist/client/unlogged/img/login-logo-icon.svg',
|
|
2272
|
-
'unlogged/img/login-logo-icon.png',
|
|
2273
|
-
'dist/unlogged/img/login-logo-icon.png',
|
|
2274
|
-
'dist/client/unlogged/img/login-logo-icon.png',
|
|
2275
|
-
'unlogged/img/logo.png',
|
|
2276
|
-
'dist/unlogged/img/logo.png',
|
|
2277
|
-
'dist/client/unlogged/img/logo.png',
|
|
2278
|
-
'client/img/logo.png',
|
|
2279
|
-
'dist/client/img/logo.png',
|
|
2280
|
-
'dist/client/client/img/logo.png',
|
|
2270
|
+
'unlogged/img/login-logo-icon.svg',
|
|
2271
|
+
'dist/unlogged/img/login-logo-icon.svg',
|
|
2272
|
+
'dist/client/unlogged/img/login-logo-icon.svg',
|
|
2273
|
+
'unlogged/img/login-logo-icon.png',
|
|
2274
|
+
'dist/unlogged/img/login-logo-icon.png',
|
|
2275
|
+
'dist/client/unlogged/img/login-logo-icon.png',
|
|
2276
|
+
'unlogged/img/logo.png',
|
|
2277
|
+
'dist/unlogged/img/logo.png',
|
|
2278
|
+
'dist/client/unlogged/img/logo.png',
|
|
2279
|
+
'client/img/logo.png',
|
|
2280
|
+
'dist/client/img/logo.png',
|
|
2281
|
+
'dist/client/client/img/logo.png',
|
|
2281
2282
|
'unlogged/img/logo-128.png',
|
|
2282
2283
|
'dist/unlogged/img/logo-128.png',
|
|
2283
|
-
'dist/client/unlogged/img/logo-128.png'
|
|
2284
|
+
'dist/client/unlogged/img/logo-128.png'
|
|
2284
2285
|
];
|
|
2285
2286
|
buscar = buscar.map(n=>be.rootPath+'/'+n);
|
|
2286
2287
|
buscar.push(__dirname+'/../for-client/img/login-logo-icon.png');
|
|
@@ -2295,7 +2296,7 @@ AppBackend.prototype.addUnloggedServices = function addUnloggedServices(mainApp,
|
|
|
2295
2296
|
be.clientIncludesCompleted(null).filter(x => x.module).forEach(function (moduleDef) {
|
|
2296
2297
|
if(baseUrl=='/'){
|
|
2297
2298
|
baseUrl='';
|
|
2298
|
-
}
|
|
2299
|
+
}
|
|
2299
2300
|
let baseLib = baseUrl + '/' + (moduleDef.path ? moduleDef.path : be.esJavascript(moduleDef.type)? 'lib': 'css');
|
|
2300
2301
|
resolve_module_dir(moduleDef.module, moduleDef.modPath, moduleDef.file ?? '.')
|
|
2301
2302
|
try {
|
|
@@ -2319,7 +2320,7 @@ AppBackend.prototype.addUnloggedServices = function addUnloggedServices(mainApp,
|
|
|
2319
2320
|
// ----------------------------------------------------
|
|
2320
2321
|
var skin=be.config['client-setup'].skin;
|
|
2321
2322
|
var skinUrl=(skin?skin+'/':'');
|
|
2322
|
-
var optsGenericForFilesUnlogged=be.optsGenericForFiles();
|
|
2323
|
+
var optsGenericForFilesUnlogged=be.optsGenericForFiles();
|
|
2323
2324
|
var skinPaths=[Path.join(be.rootPath,'skins')];
|
|
2324
2325
|
if(be.config.server.skins[skin]['local-path']){
|
|
2325
2326
|
skinPaths=skinPaths.concat(be.config.server.skins[skin]['local-path']).map(function(path){
|
|
@@ -2372,7 +2373,7 @@ AppBackend.prototype.getVisibleMenu = function getVisibleMenu(menu, context){
|
|
|
2372
2373
|
|
|
2373
2374
|
AppBackend.prototype.clientIncludes = function clientIncludes(req, opts) {
|
|
2374
2375
|
const hideBEPlusInclusions = opts === true || opts && typeof opts == "object" && opts.hideBEPlusInclusions;
|
|
2375
|
-
opts = opts === true ? {} : opts || {};
|
|
2376
|
+
opts = opts === true ? {} : opts || {};
|
|
2376
2377
|
var list = [];
|
|
2377
2378
|
if (!hideBEPlusInclusions) {
|
|
2378
2379
|
list = [
|
|
@@ -2463,7 +2464,7 @@ AppBackend.prototype.clientModules = function clientModules(req, opts) {
|
|
|
2463
2464
|
}
|
|
2464
2465
|
|
|
2465
2466
|
/**
|
|
2466
|
-
* @param {string} tableName
|
|
2467
|
+
* @param {string} tableName
|
|
2467
2468
|
* @param {(tableDef:typesOpe.TableDefinition, context?:TableContext)=>void} appenderFunction
|
|
2468
2469
|
*/
|
|
2469
2470
|
AppBackend.prototype.appendToTableDefinition = function appendToTableDefinition(tableName, appenderFunction){
|
|
@@ -2520,16 +2521,16 @@ AppBackend.prototype.csss = function csss(hideBEPlusInclusions){
|
|
|
2520
2521
|
AppBackend.prototype.scanSkinFiles = function scanSkinFiles() {
|
|
2521
2522
|
var be = this;
|
|
2522
2523
|
var skinName = be.config['client-setup'].skin;
|
|
2523
|
-
be.activeSkinFiles = new Set();
|
|
2524
|
+
be.activeSkinFiles = new Set();
|
|
2524
2525
|
|
|
2525
2526
|
var skinConfig = be.config.server.skins && be.config.server.skins[skinName];
|
|
2526
2527
|
|
|
2527
2528
|
if (skinName && skinConfig && skinConfig['local-path']) {
|
|
2528
2529
|
try {
|
|
2529
2530
|
var skinPath = Path.join(Path.resolve(skinConfig['local-path']), skinName);
|
|
2530
|
-
|
|
2531
|
+
|
|
2531
2532
|
if (fs.existsSync(skinPath)) {
|
|
2532
|
-
|
|
2533
|
+
|
|
2533
2534
|
const walk = (currentPath) => {
|
|
2534
2535
|
const entries = fs.readdirSync(currentPath, { withFileTypes: true });
|
|
2535
2536
|
|
|
@@ -2544,7 +2545,7 @@ AppBackend.prototype.scanSkinFiles = function scanSkinFiles() {
|
|
|
2544
2545
|
var relativePath = Path.relative(skinPath, fullPath)
|
|
2545
2546
|
.replace(/\\/g, '/')
|
|
2546
2547
|
.replace(/^\//, '');
|
|
2547
|
-
|
|
2548
|
+
|
|
2548
2549
|
be.activeSkinFiles.add(relativePath);
|
|
2549
2550
|
}
|
|
2550
2551
|
}
|
|
@@ -2631,7 +2632,7 @@ AppBackend.prototype.mainPage = function mainPage(req, offlineMode, opts){
|
|
|
2631
2632
|
|
|
2632
2633
|
var lastDotIndex = css.lastIndexOf('.');
|
|
2633
2634
|
var cssBase = (lastDotIndex !== -1) ? css.substring(0, lastDotIndex) : css;
|
|
2634
|
-
|
|
2635
|
+
|
|
2635
2636
|
var existsInSkin = EXTENSIONES_SKIN.some(function(ext) {
|
|
2636
2637
|
return be.activeSkinFiles.has(cssBase + ext);
|
|
2637
2638
|
});
|
|
@@ -2897,7 +2898,7 @@ AppBackend.prototype.validateBitacora = function validateBitacora(procedureDef){
|
|
|
2897
2898
|
var tableDefFields = be.tableStructures[procedureDef.bitacora.targetTable](contextForDump).fields;
|
|
2898
2899
|
var targetTableBitacoraFields = procedureDef.bitacora.targetTableBitacoraFields;
|
|
2899
2900
|
for (var fieldForSearch in targetTableBitacoraFields) {
|
|
2900
|
-
var searchResult = tableDefFields.find(function findByName(field) {
|
|
2901
|
+
var searchResult = tableDefFields.find(function findByName(field) {
|
|
2901
2902
|
return field.name === targetTableBitacoraFields[fieldForSearch];
|
|
2902
2903
|
});
|
|
2903
2904
|
if(!searchResult){
|
|
@@ -2905,12 +2906,12 @@ AppBackend.prototype.validateBitacora = function validateBitacora(procedureDef){
|
|
|
2905
2906
|
}
|
|
2906
2907
|
}
|
|
2907
2908
|
var targetTableUpdateFieldsCondition = procedureDef.bitacora.targetTableUpdateFieldsCondition || ['init_date','end_date','has_error', 'end_status'];
|
|
2908
|
-
if(targetTableUpdateFieldsCondition){
|
|
2909
|
+
if(targetTableUpdateFieldsCondition){
|
|
2909
2910
|
if(targetTableUpdateFieldsCondition.length == 0){
|
|
2910
2911
|
throw Error("Bitacora bad definition in core function '" + procedureDef.action + "', targetTableUpdateFieldsCondition must to be defined for table '" + procedureDef.bitacora.targetTable + "'.");
|
|
2911
2912
|
}
|
|
2912
2913
|
targetTableUpdateFieldsCondition.forEach(function(fieldName){
|
|
2913
|
-
var searchResult = tableDefFields.find(function findByName(field) {
|
|
2914
|
+
var searchResult = tableDefFields.find(function findByName(field) {
|
|
2914
2915
|
return field.name === fieldName;
|
|
2915
2916
|
});
|
|
2916
2917
|
if(!searchResult){
|
|
@@ -3040,9 +3041,9 @@ AppBackend.prototype.dumpDbTableFields = function dumpDbTableFields(tableDef, op
|
|
|
3040
3041
|
(fieldDef.dataDecimals?','+fieldDef.dataDecimals:'')
|
|
3041
3042
|
+')':fieldType)+
|
|
3042
3043
|
( be.specialSqlDefaultExpressions[fieldDef.defaultDbValue] != null ? ' default ' + be.specialSqlDefaultExpressions[fieldDef.defaultDbValue]
|
|
3043
|
-
: fieldDef.defaultDbValue != null ? ' default ' + fieldDef.defaultDbValue
|
|
3044
|
+
: fieldDef.defaultDbValue != null ? ' default ' + fieldDef.defaultDbValue
|
|
3044
3045
|
: be.specialSqlDefaultExpressions[fieldDef.specialDefaultValue] != null ? ' default ' + be.specialSqlDefaultExpressions[fieldDef.specialDefaultValue]
|
|
3045
|
-
: fieldDef.defaultValue != null ? ' default ' + db.quoteLiteral(fieldDef.defaultValue)
|
|
3046
|
+
: fieldDef.defaultValue != null ? ' default ' + db.quoteLiteral(fieldDef.defaultValue)
|
|
3046
3047
|
: ''
|
|
3047
3048
|
) +
|
|
3048
3049
|
(be.isGeneratedSequence(fieldDef.sequence)?' generated always as identity':'')+
|
|
@@ -3195,7 +3196,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
|
|
|
3195
3196
|
lines.push(');');
|
|
3196
3197
|
//TODO: REFACTOR: Hacerlo mas sencillo
|
|
3197
3198
|
// este codigo se encarga de convertir a rights de sql nuestros propios rights
|
|
3198
|
-
// por ej (import -> [insert, update])
|
|
3199
|
+
// por ej (import -> [insert, update])
|
|
3199
3200
|
var allows = tableDef.allow;
|
|
3200
3201
|
var appToSqlRights = {'import': ['insert', 'update'], 'export': ['select'], 'deleteAll': ['delete']};
|
|
3201
3202
|
[ 'import', 'export', 'deleteAll'].filter(function(right){
|
|
@@ -3252,7 +3253,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
|
|
|
3252
3253
|
var prefix = 'alter table '+cualQuoteTableName+' add '+
|
|
3253
3254
|
(cons.consName?'constraint '+db.quoteIdent(cons.consName)+' ':'');
|
|
3254
3255
|
switch(cons.constraintType){
|
|
3255
|
-
case 'unique':
|
|
3256
|
+
case 'unique':
|
|
3256
3257
|
sql='('+cons.fields.map(function(field){ return db.quoteIdent(field); }).join(', ')+')';
|
|
3257
3258
|
if(cons.where){
|
|
3258
3259
|
if(cons.consName == null){
|
|
@@ -3264,10 +3265,10 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
|
|
|
3264
3265
|
prefix += 'unique ';
|
|
3265
3266
|
}
|
|
3266
3267
|
break;
|
|
3267
|
-
case 'check':
|
|
3268
|
+
case 'check':
|
|
3268
3269
|
sql='check ('+cons.expr+')';
|
|
3269
3270
|
break;
|
|
3270
|
-
case 'exclude':
|
|
3271
|
+
case 'exclude':
|
|
3271
3272
|
sql=`exclude using ${cons.using} (${cons.fields.map(f => typeof f == "string"?`${f} WITH =`:`${f.fieldName} WITH ${f.operator}`).join(', ')})${cons.where ? ` WHERE (${cons.where})`:``}`;
|
|
3272
3273
|
break;
|
|
3273
3274
|
default:
|
|
@@ -3310,7 +3311,7 @@ AppBackend.prototype.dumpDbSchemaPartial = async function dumpDbSchemaPartial(pa
|
|
|
3310
3311
|
(polcom.using? ` USING ( ${polcom.using} )`:'')+
|
|
3311
3312
|
(polcom.check?` WITH CHECK ( ${polcom.check} )`:'')+';'
|
|
3312
3313
|
);
|
|
3313
|
-
}
|
|
3314
|
+
}
|
|
3314
3315
|
});
|
|
3315
3316
|
}
|
|
3316
3317
|
}else{
|
|
@@ -3351,7 +3352,7 @@ begin
|
|
|
3351
3352
|
else
|
|
3352
3353
|
select ${be.config.login.infoFieldList.map(fieldName => db.quoteIdent(fieldName)).join(', ')}
|
|
3353
3354
|
into ${be.config.login.infoFieldList.map(fieldName => db.quoteIdent('v_'+fieldName)).join(', ')}
|
|
3354
|
-
|
|
3355
|
+
|
|
3355
3356
|
from ${(be.config.login.from ?? (
|
|
3356
3357
|
(be.config.login.schema?be.db.quoteIdent(be.config.login.schema)+'.':'')+
|
|
3357
3358
|
be.db.quoteIdent(be.config.login.table)))}
|
|
@@ -3362,7 +3363,7 @@ begin
|
|
|
3362
3363
|
set backend_plus._mode = normal;
|
|
3363
3364
|
end if;
|
|
3364
3365
|
perform set_config('backend_plus._user', p_username, false);
|
|
3365
|
-
end;
|
|
3366
|
+
end;
|
|
3366
3367
|
$body$;
|
|
3367
3368
|
|
|
3368
3369
|
`)
|
|
@@ -3376,7 +3377,7 @@ $body$;
|
|
|
3376
3377
|
var allTableContent = await fs.readFile('install/local-dump.psql','utf-8');
|
|
3377
3378
|
var startIndex = allTableContent.indexOf('-- Data for Name: ');
|
|
3378
3379
|
console.log('startIndex', startIndex);
|
|
3379
|
-
var lastUseful = allTableContent.lastIndexOf('\nSELECT pg_catalog.setval')
|
|
3380
|
+
var lastUseful = allTableContent.lastIndexOf('\nSELECT pg_catalog.setval')
|
|
3380
3381
|
console.log('lastUseful', lastUseful);
|
|
3381
3382
|
if (lastUseful == -1) lastUseful = allTableContent.lastIndexOf('\n\\.\n');
|
|
3382
3383
|
console.log('lastUseful', lastUseful);
|
|
@@ -3422,6 +3423,7 @@ $body$;
|
|
|
3422
3423
|
return {path:Path.relative(process.cwd(),theTableFileName),content};
|
|
3423
3424
|
});
|
|
3424
3425
|
}).then(function({path,content}){
|
|
3426
|
+
/* LETRUA DEL ARCHIVO .TAB */
|
|
3425
3427
|
dataText.push("\n-- table data: "+path);
|
|
3426
3428
|
var lines;
|
|
3427
3429
|
var rows;
|
|
@@ -3489,7 +3491,7 @@ $body$;
|
|
|
3489
3491
|
throw Error("no se encuentra la columna "+filteredFieldDef[i]+" en "+tableName);
|
|
3490
3492
|
}
|
|
3491
3493
|
return value==='' ? (
|
|
3492
|
-
def.allowEmptyText && ('nullable' in def) && !def.nullable ? "''" : 'null'
|
|
3494
|
+
def.allowEmptyText && ('nullable' in def) && !def.nullable ? "''" : 'null'
|
|
3493
3495
|
) : db.quoteNullable(value);
|
|
3494
3496
|
}).join(', ')+")";
|
|
3495
3497
|
}).join(',\n')+';\n';
|
|
@@ -3524,7 +3526,7 @@ $body$;
|
|
|
3524
3526
|
]
|
|
3525
3527
|
.map(async function(fileNames){
|
|
3526
3528
|
if (!fileNames) return '';
|
|
3527
|
-
var i = 0;
|
|
3529
|
+
var i = 0;
|
|
3528
3530
|
return (await Promise.all(fileNames.map(async fileName => {
|
|
3529
3531
|
var content;
|
|
3530
3532
|
do {
|
|
@@ -3576,7 +3578,7 @@ $body$;
|
|
|
3576
3578
|
'\n-- functions\n' + functionLines.join('\n')+
|
|
3577
3579
|
'\n-- lines \n' + lines.join('\n')+
|
|
3578
3580
|
(complete? ('\n\n-- pre-ADAPTs\n'+texts[1]+'\n\n') : '' )+
|
|
3579
|
-
(complete? ('\n\n-- DATA\n'+ dataText.join('\n')) : '' )+
|
|
3581
|
+
(complete? ('\n\n-- DATA\n'+ dataText.join('\n')) : '' )+
|
|
3580
3582
|
(complete? ('\n\n-- ADAPTs\n'+ texts[2]+'\n\n') : '' )+
|
|
3581
3583
|
'\n-- conss\n' + consLines.join('\n')+
|
|
3582
3584
|
'\n-- FKs\n' + fkLines.join('\n')+
|
|
@@ -3606,14 +3608,17 @@ AppBackend.prototype.getDbFunctions = async function (){
|
|
|
3606
3608
|
AppBackend.prototype.dumpDbSchema = async function dumpDbSchema(opts){
|
|
3607
3609
|
var be = this;
|
|
3608
3610
|
var {mainSql,enancePart} = await be.dumpDbSchemaPartial(
|
|
3609
|
-
opts.complete?be.tableStructures:likeAr(be.tableStructures).filter((_, name)=>opts.tableNames.includes(name)),
|
|
3611
|
+
opts.complete?be.tableStructures:likeAr(be.tableStructures).filter((_, name)=>opts.tableNames.includes(name)),
|
|
3610
3612
|
opts
|
|
3611
3613
|
)
|
|
3612
3614
|
mainSql=be.config.install.dump.db.extensions.map(function(extension){
|
|
3613
3615
|
return ({
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3616
|
+
cube : "create extension if not exists cube ;",
|
|
3617
|
+
earthdistance : "create extension if not exists earthdistance ;",
|
|
3618
|
+
gist : "create extension if not exists btree_gist ;",
|
|
3619
|
+
pg_trgm : "create extension if not exists pg_trgm ;",
|
|
3620
|
+
pgcrypto : "create extension if not exists pgcrypto ;",
|
|
3621
|
+
postgis : "create extension if not exists postgis ;",
|
|
3617
3622
|
}[extension]||('--unknown exension '+extension))+'\n';
|
|
3618
3623
|
}).join('')+mainSql;
|
|
3619
3624
|
await fs.writeFile('local-db-dump.sql', mainSql);
|
|
@@ -3686,7 +3691,7 @@ AppBackend.prototype.transformInput = function transformInput(fieldDef, value){
|
|
|
3686
3691
|
return value;
|
|
3687
3692
|
}
|
|
3688
3693
|
|
|
3689
|
-
/**
|
|
3694
|
+
/**
|
|
3690
3695
|
* xxxparam {{ action:string, parameters:any, conRegistro:boolean, conPadron:boolean, fileName?:string, csvFileName?:string, csvSeparator?:string, queries:{titulo:string, sql:string, params:string[]}[] }}
|
|
3691
3696
|
* @param {{title:string, rows:Record<string, any>[]}[]} result
|
|
3692
3697
|
* @returns {Promise<void>}
|
|
@@ -3784,7 +3789,7 @@ AppBackend.prototype.exportacionesGenerico = async function exportacionesGeneric
|
|
|
3784
3789
|
))
|
|
3785
3790
|
}
|
|
3786
3791
|
return [
|
|
3787
|
-
...(fileName?[{url:fileName, label:csvFileName?'xlsx de control':fileName}]:[]),
|
|
3792
|
+
...(fileName?[{url:fileName, label:csvFileName?'xlsx de control':fileName}]:[]),
|
|
3788
3793
|
...(csvFileName?[{url:csvFileName, label:fileName?'csv (formato UTF-8)':csvFileName}]:[]),
|
|
3789
3794
|
];
|
|
3790
3795
|
}
|
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.7.0-beta.
|
|
4
|
+
"version": "2.7.0-beta.4",
|
|
5
5
|
"author": "Codenautas <codenautas@googlegroups.com>",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": "codenautas/backend-plus",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"ensure-login": "^0.1.6-beta.0",
|
|
47
47
|
"express": "^5.2.1",
|
|
48
48
|
"express-useragent": "^2.2.1",
|
|
49
|
-
"fs-extra": "^11.
|
|
49
|
+
"fs-extra": "^11.4.0",
|
|
50
50
|
"js-to-html": "^1.3.6",
|
|
51
|
-
"js-yaml": "^5.2.
|
|
51
|
+
"js-yaml": "^5.2.2",
|
|
52
52
|
"json4all": "^1.4.4",
|
|
53
53
|
"lazy-some": "^0.1.0",
|
|
54
54
|
"like-ar": "^0.5.3",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"multiparty": "^4.3.0",
|
|
60
60
|
"nodemailer": "^9.0.3",
|
|
61
61
|
"numeral": "^2.0.6",
|
|
62
|
-
"pg-promise-strict": "^1.
|
|
62
|
+
"pg-promise-strict": "^1.5.0",
|
|
63
63
|
"pg-triggers": "0.4.6",
|
|
64
64
|
"pikaday": "^1.8.2",
|
|
65
65
|
"require-bro": "^0.3.6",
|
|
@@ -68,46 +68,47 @@
|
|
|
68
68
|
"simple-git": "^3.36.0",
|
|
69
69
|
"sql-tools": "^0.1.7",
|
|
70
70
|
"stack-trace": "^1.0.0",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
71
|
+
"tab-plus": "^0.1.7",
|
|
72
|
+
"type-store": "^0.6.0",
|
|
73
|
+
"typed-controls": "^0.12.7",
|
|
73
74
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz"
|
|
74
75
|
},
|
|
75
76
|
"devDependencies": {
|
|
76
77
|
"@types/big.js": "^7.0.0",
|
|
77
|
-
"@types/expect.js": "
|
|
78
|
+
"@types/expect.js": "^0.3.32",
|
|
78
79
|
"@types/express": "^5.0.6",
|
|
79
80
|
"@types/express-useragent": "^1.0.5",
|
|
80
81
|
"@types/fs-extra": "^11.0.4",
|
|
81
82
|
"@types/js-yaml": "^4.0.9",
|
|
82
83
|
"@types/mocha": "^10.0.10",
|
|
83
|
-
"@types/multiparty": "
|
|
84
|
-
"@types/node": "^26.1.
|
|
84
|
+
"@types/multiparty": "^4.2.1",
|
|
85
|
+
"@types/node": "^26.1.1",
|
|
85
86
|
"@types/nodemailer": "^8.0.1",
|
|
86
87
|
"@types/numeral": "~2.0.5",
|
|
87
88
|
"@types/session-file-store": "^1.2.6",
|
|
88
|
-
"@types/stack-trace": "
|
|
89
|
+
"@types/stack-trace": "^0.0.33",
|
|
89
90
|
"@types/websql": "~0.0.30",
|
|
90
91
|
"backend-skins": "^0.1.34",
|
|
91
92
|
"discrepances": "^0.2.14",
|
|
92
93
|
"esprima": "^4.0.1",
|
|
93
|
-
"expect.js": "
|
|
94
|
+
"expect.js": "^0.3.1",
|
|
94
95
|
"karma": "6.4.4",
|
|
95
96
|
"karma-chrome-launcher": "^3.2.0",
|
|
96
97
|
"karma-expect": "^1.1.3",
|
|
97
98
|
"karma-firefox-launcher": "^2.1.3",
|
|
98
99
|
"karma-ie-launcher": "^1.0.0",
|
|
99
100
|
"karma-mocha": "^2.0.1",
|
|
100
|
-
"kill-9": "
|
|
101
|
+
"kill-9": "^0.4.3",
|
|
101
102
|
"mocha": "^11.7.6",
|
|
102
103
|
"nyc": "^18.0.0",
|
|
103
104
|
"puppeteer": "^25.3.0",
|
|
104
105
|
"qa-control": "0.7.5",
|
|
105
106
|
"regexplicit": "^0.1.3",
|
|
106
107
|
"self-explain": "^0.11.0",
|
|
107
|
-
"sinon": "^22.
|
|
108
|
+
"sinon": "^22.1.0",
|
|
108
109
|
"supertest": "^7.2.2",
|
|
109
|
-
"types.d.ts": "
|
|
110
|
-
"typescript": "^5.9.
|
|
110
|
+
"types.d.ts": "^0.6.22",
|
|
111
|
+
"typescript": "^5.9.2",
|
|
111
112
|
"why-is-node-running": "^3.2.2"
|
|
112
113
|
},
|
|
113
114
|
"engines": {
|
|
@@ -118,7 +119,7 @@
|
|
|
118
119
|
"test-ui": "(npm run prepublish || echo \"continue w/error\") && mocha --reporter spec --single-run --bail test/test-*.js",
|
|
119
120
|
"test-karma": "(npm run prepublish || echo \"continue w/error\") && mocha --reporter spec --bail test/test-k*.js",
|
|
120
121
|
"test-why": "node --expose-internals ./node_modules/mocha/bin/_mocha --reporter spec --bail test/test*.js",
|
|
121
|
-
"test-ci": "npm test",
|
|
122
|
+
"test-ci": "mkdir -p coverage && > coverage/lcov.info && npm test",
|
|
122
123
|
"test-cov": "(npm run prepublish || echo \"continue w/error\") && mocha --reporter spec --bail test/test*.js",
|
|
123
124
|
"test-good": "mocha --reporter spec --bail --check-leaks test/test*.js",
|
|
124
125
|
"example-pu": "node test/puppeteer/first-step.js",
|