underpost 2.7.83 → 2.7.91

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.
Files changed (60) hide show
  1. package/.github/workflows/ghpkg.yml +41 -1
  2. package/.github/workflows/pwa-microservices-template.page.yml +54 -0
  3. package/.vscode/settings.json +7 -0
  4. package/CHANGELOG.md +64 -16
  5. package/bin/cron.js +47 -0
  6. package/bin/db.js +60 -7
  7. package/bin/deploy.js +345 -15
  8. package/bin/file.js +17 -1
  9. package/bin/index.js +1 -1
  10. package/bin/util.js +31 -1
  11. package/conf.js +18 -4
  12. package/docker-compose.yml +1 -1
  13. package/package.json +3 -3
  14. package/src/api/core/core.router.js +9 -9
  15. package/src/api/core/core.service.js +12 -4
  16. package/src/api/default/default.service.js +4 -4
  17. package/src/api/file/file.service.js +3 -3
  18. package/src/api/user/user.service.js +10 -8
  19. package/src/client/components/core/CommonJs.js +3 -0
  20. package/src/client/components/core/CssCore.js +30 -3
  21. package/src/client/components/core/Docs.js +110 -10
  22. package/src/client/components/core/LoadingAnimation.js +4 -2
  23. package/src/client/components/core/Modal.js +224 -22
  24. package/src/client/components/core/Panel.js +1 -1
  25. package/src/client/components/core/PanelForm.js +2 -1
  26. package/src/client/components/core/Responsive.js +34 -5
  27. package/src/client/components/core/RichText.js +4 -2
  28. package/src/client/components/core/WebComponent.js +44 -0
  29. package/src/client/components/core/Worker.js +13 -15
  30. package/src/client/public/default/plantuml/client-conf.svg +1 -1
  31. package/src/client/public/default/plantuml/client-schema.svg +1 -1
  32. package/src/client/public/default/plantuml/cron-conf.svg +1 -1
  33. package/src/client/public/default/plantuml/cron-schema.svg +1 -1
  34. package/src/client/public/default/plantuml/server-conf.svg +1 -1
  35. package/src/client/public/default/plantuml/server-schema.svg +1 -1
  36. package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
  37. package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
  38. package/src/client/public/default/site.webmanifest +69 -0
  39. package/src/client/ssr/components/body/CacheControl.js +1 -1
  40. package/src/client/ssr/components/head/Production.js +1 -0
  41. package/src/client/ssr/components/head/Pwa.js +146 -0
  42. package/src/client/ssr/components/head/Seo.js +14 -0
  43. package/src/client/ssr/pages/maintenance.js +14 -0
  44. package/src/client/ssr/pages/offline.js +21 -0
  45. package/src/client/sw/default.sw.js +4 -2
  46. package/src/db/DataBaseProvider.js +12 -1
  47. package/src/db/mongo/MongooseDB.js +0 -1
  48. package/src/runtime/lampp/Lampp.js +9 -9
  49. package/src/server/backup.js +82 -70
  50. package/src/server/client-build.js +46 -94
  51. package/src/server/conf.js +82 -18
  52. package/src/server/crypto.js +91 -0
  53. package/src/server/dns.js +48 -16
  54. package/src/server/network.js +94 -7
  55. package/src/server/proxy.js +27 -27
  56. package/src/server/runtime.js +4 -2
  57. package/src/server/ssl.js +2 -2
  58. package/src/client/ssr/offline/default.index.js +0 -31
  59. package/src/cron.js +0 -30
  60. package/src/server/cron.js +0 -35
package/bin/deploy.js CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  Cmd,
26
26
  restoreMacroDb,
27
27
  fixDependencies,
28
+ setUpProxyMaintenanceServer,
28
29
  } from '../src/server/conf.js';
29
30
  import { buildClient } from '../src/server/client-build.js';
30
31
  import { range, setPad, timer, uniqueArray } from '../src/client/components/core/CommonJs.js';
@@ -32,6 +33,8 @@ import toJsonSchema from 'to-json-schema';
32
33
  import simpleGit from 'simple-git';
33
34
  import { MongooseDB } from '../src/db/mongo/MongooseDB.js';
34
35
  import { Lampp } from '../src/runtime/lampp/Lampp.js';
36
+ import { DefaultConf } from '../conf.js';
37
+ import { JSONweb } from '../src/server/client-formatted.js';
35
38
 
36
39
  const logger = loggerFactory(import.meta);
37
40
 
@@ -152,10 +155,15 @@ try {
152
155
  await deployRun(dataDeploy);
153
156
  } else {
154
157
  loadConf(process.argv[3]);
155
- shellExec(`npm start ${process.argv[3]}`);
158
+ shellExec(`npm start ${process.argv.includes('maintenance') ? 'maintenance' : ''}`);
156
159
  }
157
160
  }
158
161
  break;
162
+
163
+ case 'remove-await-deploy': {
164
+ if (fs.existsSync(`./tmp/await-deploy`)) fs.remove(`./tmp/await-deploy`);
165
+ break;
166
+ }
159
167
  case 'new-nodejs-app':
160
168
  {
161
169
  const deployId = process.argv[3];
@@ -222,21 +230,18 @@ try {
222
230
  break;
223
231
  case 'build-full-client':
224
232
  {
233
+ if (!process.argv[3]) process.argv[3] = 'default';
225
234
  const { deployId, folder } = loadConf(process.argv[3]);
226
235
 
227
- let argHost = process.argv[4] ? process.argv[4].split(',') : undefined;
228
- let argPath = process.argv[5] ? process.argv[5].split(',') : undefined;
236
+ let argHost = process.argv[4] ? process.argv[4].split(',') : [];
237
+ let argPath = process.argv[5] ? process.argv[5].split(',') : [];
229
238
  let deployIdSingleReplicas = [];
230
239
  const serverConf = deployId
231
240
  ? JSON.parse(fs.readFileSync(`./conf/conf.server.json`, 'utf8'))
232
241
  : Config.default.server;
233
- if (!deployId) {
234
- argHost = 'default.net';
235
- argPath = '/';
236
- }
237
242
  for (const host of Object.keys(serverConf)) {
238
243
  for (const path of Object.keys(serverConf[host])) {
239
- if (argHost && argPath && (!argHost.includes(host) || !argPath.includes(path))) {
244
+ if (argHost.length && argPath.length && (!argHost.includes(host) || !argPath.includes(path))) {
240
245
  delete serverConf[host][path];
241
246
  } else {
242
247
  serverConf[host][path].liteBuild = process.argv.includes('l') ? true : false;
@@ -278,6 +283,154 @@ try {
278
283
  }
279
284
  break;
280
285
 
286
+ case 'adminer': {
287
+ const directory = '/dd/engine/public/adminer';
288
+ // const host = '127.0.0.1';
289
+ const host = 'localhost';
290
+ const port = 80;
291
+ if (!process.argv.includes('server')) {
292
+ if (fs.existsSync(directory)) fs.removeSync(directory);
293
+ fs.mkdirSync(directory, { recursive: true });
294
+ shellExec(`cd ${directory} && wget https://www.adminer.org/latest.php -O adminer.php`);
295
+ }
296
+ Lampp.removeRouter();
297
+ Lampp.appendRouter(` Listen ${port}
298
+ <VirtualHost *:${port}>
299
+ DocumentRoot "${directory}"
300
+ ServerName ${host}:${port}
301
+
302
+ <Directory "${directory}">
303
+ Options Indexes FollowSymLinks MultiViews
304
+ AllowOverride All
305
+ Require all granted
306
+ </Directory>
307
+
308
+ </VirtualHost>
309
+ `);
310
+ if (Lampp.enabled() && Lampp.router) Lampp.initService({ daemon: true });
311
+ shellExec(`open /opt/lampp/apache2/conf/httpd.conf`);
312
+ break;
313
+ }
314
+
315
+ case 'pma':
316
+ {
317
+ const directory = '/dd/engine/public/phpmyadmin';
318
+ // const host = '127.0.0.1';
319
+ const host = 'localhost';
320
+ const port = 80;
321
+ // data config path: /etc/phpmyadmin
322
+
323
+ // The config.inc.php file is not required, and only needed for custom configurations
324
+
325
+ // phpmyadmin will first refer to ./libraries/config.default.php to retrieve the default values.
326
+
327
+ // If for some reason you need to modify the default values, and the ./config.inc.php
328
+ // file doesn't exist, you will need to create one as per the Installation documentation.
329
+
330
+ // You will also need to configure pmadb for some of phpmyadmin's special features such as bookmarks.
331
+
332
+ // CREATE USER 'pma'@'localhost' IDENTIFIED VIA mysql_native_password USING 'pmapass';
333
+ // GRANT SELECT, INSERT, UPDATE, DELETE ON `<pma_db>`.* TO 'pma'@'localhost';
334
+
335
+ if (!process.argv.includes('server')) {
336
+ // if (fs.existsSync(directory)) fs.removeSync(directory);
337
+ shellExec(`sudo apt install phpmyadmin php-mbstring php-zip php-gd php-json php-curl`);
338
+ shellExec(`sudo phpenmod mbstring`);
339
+ shellExec(
340
+ `cd /usr/share/phpmyadmin && git init && git add . && git commit -m "Base phpMyAdmin implementation"`,
341
+ );
342
+ }
343
+
344
+ // if (!fs.existsSync(directory)) fs.mkdirSync(directory, { recursive: true });
345
+ // if (!fs.existsSync('./public/phpmyadmin/phpmyadmin'))
346
+ // fs.copySync('/usr/share/phpmyadmin', './public/phpmyadmin/phpmyadmin');
347
+
348
+ Lampp.removeRouter();
349
+ Lampp.appendRouter(` Listen ${port} `);
350
+ if (Lampp.enabled() && Lampp.router) Lampp.initService({ daemon: true });
351
+ // shellExec(`open /opt/lampp/apache2/conf/httpd.conf`);
352
+
353
+ // Create a link in /var/www like this:
354
+
355
+ // sudo ln -s /usr/share/phpmyadmin /var/www/
356
+
357
+ // Note: since 14.04 you may want to use /var/www/html/ instead of /var/www/
358
+
359
+ // If that's not working for you, you need to include PHPMyAdmin inside apache configuration.
360
+
361
+ // Open apache.conf using your favorite editor, mine is vim :)
362
+
363
+ // sudo vim /etc/apache2/apache2.conf
364
+
365
+ // Then add the following line:
366
+
367
+ // Include /etc/phpmyadmin/apache.conf
368
+
369
+ // For Ubuntu 15.04 and 16.04
370
+
371
+ // sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-available/phpmyadmin.conf
372
+ // sudo a2enconf phpmyadmin.conf
373
+ // sudo service apache2 reload
374
+ break;
375
+ Lampp.appendRouter(` Listen ${port}
376
+
377
+ <VirtualHost *:${port}>
378
+ DocumentRoot "${directory}"
379
+ ServerName ${host}:${port}
380
+
381
+ <Directory "${directory}">
382
+ Options Indexes FollowSymLinks MultiViews
383
+ AllowOverride All
384
+ Require all granted
385
+ </Directory>
386
+
387
+ </VirtualHost>`);
388
+ // phpMyAdmin default Apache configuration:
389
+ Lampp.appendRouter(`
390
+
391
+ Listen ${port}
392
+
393
+ Alias /phpmyadmin /usr/share/phpmyadmin
394
+
395
+ <Directory /usr/share/phpmyadmin>
396
+ Options Indexes FollowSymLinks
397
+ DirectoryIndex index.php
398
+
399
+ <IfModule mod_php5.c>
400
+ AddType application/x-httpd-php .php
401
+
402
+ php_flag magic_quotes_gpc Off
403
+ php_flag track_vars On
404
+ php_flag register_globals Off
405
+ php_value include_path .
406
+ </IfModule>
407
+
408
+ </Directory>
409
+
410
+ # Authorize for setup
411
+ <Directory /usr/share/phpmyadmin/setup>
412
+ <IfModule mod_authn_file.c>
413
+ AuthType Basic
414
+ AuthName "phpMyAdmin Setup"
415
+ AuthUserFile /etc/phpmyadmin/htpasswd.setup
416
+ </IfModule>
417
+ Require valid-user
418
+ </Directory>
419
+
420
+ # Disallow web access to directories that don't need it
421
+ <Directory /usr/share/phpmyadmin/libraries>
422
+ Order Deny,Allow
423
+ Deny from All
424
+ </Directory>
425
+ <Directory /usr/share/phpmyadmin/setup/lib>
426
+ Order Deny,Allow
427
+ Deny from All
428
+ </Directory>
429
+
430
+ `);
431
+ }
432
+ break;
433
+
281
434
  case 'update-package':
282
435
  const files = await fs.readdir(`./engine-private/conf`, { recursive: true });
283
436
  const originPackage = JSON.parse(fs.readFileSync(`./package.json`, 'utf8'));
@@ -294,21 +447,37 @@ try {
294
447
  {
295
448
  if (fs.existsSync(`./tmp/await-deploy`)) fs.remove(`./tmp/await-deploy`);
296
449
  const dataDeploy = getDataDeploy({ deployGroupId: process.argv[3], buildSingleReplica: true });
297
- await deployRun(dataDeploy, true);
450
+ if (!process.argv[4]) await setUpProxyMaintenanceServer({ deployGroupId: process.argv[3] });
451
+ await deployRun(
452
+ process.argv[4] ? dataDeploy.filter((d) => d.deployId.match(process.argv[4])) : dataDeploy,
453
+ true,
454
+ );
298
455
  }
299
456
  break;
300
457
 
301
- case 'run-macro-build':
458
+ case 'build-macro':
302
459
  {
303
- if (fs.existsSync(`./tmp/await-deploy`)) fs.remove(`./tmp/await-deploy`);
304
460
  const dataDeploy = getDataDeploy({ deployGroupId: process.argv[3], buildSingleReplica: true });
305
461
  for (const deploy of dataDeploy) {
306
- shellExec(Cmd.conf(deploy.deployId));
307
- shellExec(Cmd.build(deploy.deployId));
462
+ if (!process.argv[4] || (process.argv[4] && process.argv[4] === deploy.deployId)) {
463
+ shellExec(Cmd.conf(deploy.deployId));
464
+ shellExec(Cmd.build(deploy.deployId));
465
+ }
308
466
  }
309
- await deployRun(dataDeploy, true);
310
467
  }
311
468
  break;
469
+ case 'macro': {
470
+ shellExec(`git checkout .`);
471
+ shellExec(`node bin/deploy build-macro ${process.argv.slice(3).join(' ')}`);
472
+ shellExec(`git checkout .`);
473
+ shellExec(`node bin/deploy run-macro ${process.argv.slice(3).join(' ')}`);
474
+ break;
475
+ }
476
+
477
+ case 'keep-server': {
478
+ await setUpProxyMaintenanceServer({ deployGroupId: process.argv[3] });
479
+ break;
480
+ }
312
481
  case 'prometheus':
313
482
  case 'prom':
314
483
  {
@@ -452,7 +621,7 @@ try {
452
621
  `./engine-private/replica/${replicaDeployId}/package.json`,
453
622
  fs
454
623
  .readFileSync(`./engine-private/replica/${replicaDeployId}/package.json`, 'utf8')
455
- .replaceAll(`--name ${deployId}`, `--name ${replicaDeployId}`),
624
+ .replaceAll(`${deployId}`, `${replicaDeployId}`),
456
625
  'utf8',
457
626
  );
458
627
  }
@@ -666,6 +835,167 @@ ${uniqueArray(logs.all.map((log) => `- ${log.author_name} ([${log.author_email}]
666
835
  break;
667
836
  }
668
837
 
838
+ case 'update-default-conf': {
839
+ const host = process.argv[3] ? process.argv[3] : 'underpostnet.github.io';
840
+ const path = process.argv[4] ? process.argv[4] : '/pwa-microservices-template-ghpkg';
841
+ DefaultConf.server = {
842
+ [host]: { [path]: DefaultConf.server['default.net']['/'] },
843
+ };
844
+ DefaultConf.server[host][path].apiBaseProxyPath = '/';
845
+ DefaultConf.server[host][path].apiBaseHost = 'www.nexodev.org';
846
+ fs.writeFileSync(
847
+ './conf.js',
848
+ `
849
+ const DefaultConf = ${JSONweb(DefaultConf)};
850
+
851
+ export { DefaultConf }
852
+
853
+ `,
854
+ 'utf8',
855
+ );
856
+
857
+ break;
858
+ }
859
+ case 'ssh-export-server-keys': {
860
+ fs.copyFile('/etc/ssh/ssh_host_rsa_key', './engine-private/deploy/ssh_host_rsa_key');
861
+ fs.copyFile('/etc/ssh/ssh_host_rsa_key.pub', './engine-private/deploy/ssh_host_rsa_key.pub');
862
+ break;
863
+ }
864
+ case 'ssh-import-server-keys': {
865
+ fs.copyFile('./engine-private/deploy/ssh_host_rsa_key', '/etc/ssh/ssh_host_rsa_key');
866
+ fs.copyFile('./engine-private/deploy/ssh_host_rsa_key.pub', '/etc/ssh/ssh_host_rsa_key.pub');
867
+ break;
868
+ }
869
+ case 'ssh-import-client-keys': {
870
+ const host = process.argv[3];
871
+ shellExec(`node bin/deploy set-ssh-keys ./engine-private/deploy/ssh_host_rsa_key${host ? ` ${host}` : ``} clean`);
872
+ break;
873
+ }
874
+ case 'ssh-keys': {
875
+ // create ssh keys
876
+ const sshAccount = process.argv[3]; // [sudo username]@[host/ip]
877
+ const destPath = process.argv[4];
878
+ // shellExec(`ssh-keygen -t ed25519 -C "${sshAccount}" -f ${destPath}`);
879
+ if (fs.existsSync(destPath)) {
880
+ fs.removeSync(destPath);
881
+ fs.removeSync(destPath + '.pub');
882
+ }
883
+ shellExec(`ssh-keygen -t rsa -b 4096 -C "${sshAccount}" -f ${destPath}`);
884
+ // add host to keyscan
885
+ // shellExec(`ssh-keyscan -t rsa ${sshAccount.split(`@`)[1]} >> ~/.ssh/known_hosts`);
886
+ break;
887
+ }
888
+
889
+ case 'set-ssh-keys': {
890
+ const files = ['authorized_keys', 'id_rsa', 'id_rsa.pub', 'known_hosts ', 'known_hosts.old'];
891
+
892
+ // > write
893
+ // >> append
894
+
895
+ // /root/.ssh/id_rsa
896
+ // /root/.ssh/id_rsa.pub
897
+ if (process.argv.includes('clean')) {
898
+ for (const file of files) {
899
+ if (fs.existsSync(`/root/.ssh/${file}`)) {
900
+ logger.info('remove', `/root/.ssh/${file}`);
901
+ fs.removeSync(`/root/.ssh/${file}`);
902
+ }
903
+ fs.writeFileSync(`/root/.ssh/${file}`, '', 'utf8');
904
+ }
905
+ shellExec('eval `ssh-agent -s`' + ` && ssh-add -D`);
906
+ }
907
+
908
+ const destPath = process.argv[3];
909
+ const sshAuthKeyTarget = '/root/.ssh/authorized_keys';
910
+ if (!fs.existsSync(sshAuthKeyTarget)) shellExec(`touch ${sshAuthKeyTarget}`);
911
+ shellExec(`cat ${destPath}.pub > ${sshAuthKeyTarget}`);
912
+ shellExec(`cat ${destPath} >> ${sshAuthKeyTarget}`);
913
+
914
+ if (!fs.existsSync('/root/.ssh/id_rsa')) shellExec(`touch ${'/root/.ssh/id_rsa'}`);
915
+ shellExec(`cat ${destPath} > ${'/root/.ssh/id_rsa'}`);
916
+
917
+ if (!fs.existsSync('/root/.ssh/id_rsa.pub')) shellExec(`touch ${'/root/.ssh/id_rsa.pub'}`);
918
+ shellExec(`cat ${destPath}.pub > ${'/root/.ssh/id_rsa.pub'}`);
919
+
920
+ shellExec(`chmod 700 /root/.ssh/`);
921
+ for (const file of files) {
922
+ shellExec(`chmod 600 /root/.ssh/${file}`);
923
+ }
924
+ const host = process.argv[4];
925
+ // add key
926
+ shellExec('eval `ssh-agent -s`' + ' && ssh-add /root/.ssh/id_rsa' + ' && ssh-add -l');
927
+ if (host) shellExec(`ssh-keyscan -H ${host} >> ~/.ssh/known_hosts`);
928
+ shellExec(`sudo systemctl enable ssh`);
929
+ shellExec(`sudo systemctl restart ssh`);
930
+ shellExec(`sudo systemctl status ssh`);
931
+
932
+ break;
933
+ }
934
+
935
+ case 'ssh': {
936
+ if (!process.argv.includes('server')) {
937
+ shellExec(`sudo apt update`);
938
+ shellExec(`sudo apt install openssh-server -y`);
939
+ shellExec(`sudo apt install ssh-askpass`);
940
+ }
941
+ shellExec(`sudo systemctl enable ssh`);
942
+ shellExec(`sudo systemctl restart ssh`);
943
+ shellExec(`sudo systemctl status ssh`);
944
+ // sudo service ssh restart
945
+ shellExec(`ip a`);
946
+
947
+ // adduser newuser
948
+ // usermod -aG sudo newuser
949
+
950
+ // ssh -i '/path/to/keyfile' username@server
951
+
952
+ // ssh-keygen -t ed25519 -C "your_email@example.com" -f $HOME/.ssh/id_rsa
953
+
954
+ // legacy: ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f $HOME/.ssh/id_rsa
955
+
956
+ // vi .ssh/authorized_keys
957
+ // chmod 700 .ssh
958
+ // chmod 600 authorized_keys
959
+
960
+ // cat id_rsa.pub > .ssh/authorized_keys
961
+
962
+ // add public key to authorized keys
963
+ // cat .ssh/id_ed25519.pub | ssh [sudo username]@[host/ip] 'cat >> .ssh/authorized_keys'
964
+
965
+ // 2. Open /etc/ssh/sshd_config file
966
+ // nano /etc/ssh/sshd_config
967
+
968
+ // 3. add example code to last line of file
969
+ // Match User newuser
970
+ // PasswordAuthentication yes
971
+
972
+ // ssh [sudo username]@[host/ip]
973
+ // open port 22
974
+
975
+ // init ssh agent service
976
+ // eval `ssh-agent -s`
977
+
978
+ // list keys
979
+ // ssh-add -l
980
+
981
+ // add key
982
+ // ssh-add /root/.ssh/id_rsa
983
+
984
+ // remove
985
+ // ssh-add -d /path/to/private/key
986
+
987
+ // remove all
988
+ // ssh-add -D
989
+
990
+ // sshpass -p ${{ secrets.PSWD }} ssh -o StrictHostKeyChecking=no -p 22 ${{ secrets.USER}}@${{ secrets.VPS_IP }} 'cd /home/adam && ./deploy.sh'
991
+
992
+ // copies the public key of your default identity (use -i identity_file for other identities) to the remote host.
993
+ // ssh-copy-id user@hostname.example.com
994
+ // ssh-copy-id "user@hostname.example.com -p <port-number>"
995
+
996
+ break;
997
+ }
998
+
669
999
  default:
670
1000
  break;
671
1001
  }
package/bin/file.js CHANGED
@@ -2,7 +2,7 @@ import fs from 'fs-extra';
2
2
 
3
3
  import { loggerFactory } from '../src/server/logger.js';
4
4
  import { cap, getCapVariableName, getDirname } from '../src/client/components/core/CommonJs.js';
5
- import { shellExec } from '../src/server/process.js';
5
+ import { shellCd, shellExec } from '../src/server/process.js';
6
6
  import walk from 'ignore-walk';
7
7
  import { validateTemplatePath } from '../src/server/conf.js';
8
8
 
@@ -76,6 +76,22 @@ try {
76
76
  fs.copySync(`./.vscode`, `../pwa-microservices-template/.vscode`);
77
77
  fs.copySync(`./.github`, `../pwa-microservices-template/.github`);
78
78
  fs.copySync(`./src/client/public/default`, `../pwa-microservices-template/src/client/public/default`);
79
+
80
+ shellCd('../pwa-microservices-template');
81
+ for (const deletePath of ['CHANGELOG.md', 'README.md', 'package-lock.json', 'package.json']) {
82
+ shellExec(`git checkout ${deletePath}`);
83
+ }
84
+ for (const deletePath of [
85
+ '.github/workflows/coverall.yml',
86
+ '.github/workflows/docker-image.yml',
87
+ '.github/workflows/deploy.ssh.yml',
88
+ '.github/workflows/deploy.api-rest.yml',
89
+ 'bin/web3.js',
90
+ 'src/ipfs.js',
91
+ 'src/k8s.js',
92
+ ]) {
93
+ fs.removeSync('../pwa-microservices-template/' + deletePath);
94
+ }
79
95
  }
80
96
 
81
97
  break;
package/bin/index.js CHANGED
@@ -19,7 +19,7 @@ const globalBinFolder = `${shellExec(`npm root -g`, {
19
19
 
20
20
  const program = new Command();
21
21
 
22
- const version = '2.7.83';
22
+ const version = '2.7.91';
23
23
 
24
24
  program.name('underpost').description(`underpost.net ci/cd cli ${version}`).version(version);
25
25
 
package/bin/util.js CHANGED
@@ -3,6 +3,8 @@ import merge from 'deepmerge';
3
3
  import si from 'systeminformation';
4
4
  import * as dir from 'path';
5
5
  import { svg } from 'font-awesome-assets';
6
+ import axios from 'axios';
7
+ import https from 'https';
6
8
 
7
9
  import { loggerFactory } from '../src/server/logger.js';
8
10
  import { shellCd, shellExec } from '../src/server/process.js';
@@ -12,6 +14,11 @@ import { Config } from '../src/server/conf.js';
12
14
  import { FileFactory } from '../src/api/file/file.service.js';
13
15
  import { buildTextImg, faBase64Png, getBufferPngText } from '../src/server/client-icons.js';
14
16
 
17
+ const httpsAgent = new https.Agent({
18
+ rejectUnauthorized: false,
19
+ });
20
+ axios.defaults.httpsAgent = httpsAgent;
21
+
15
22
  const logger = loggerFactory(import.meta);
16
23
 
17
24
  logger.info('argv', process.argv);
@@ -118,6 +125,10 @@ try {
118
125
  break;
119
126
  case 'delete-empty-folder':
120
127
  function cleanEmptyFoldersRecursively(folder) {
128
+ if (!fs.existsSync(folder)) {
129
+ logger.warn('Does not exist', folder);
130
+ return;
131
+ }
121
132
  const isDir = fs.statSync(folder).isDirectory();
122
133
  if (!isDir) return;
123
134
 
@@ -135,7 +146,11 @@ try {
135
146
 
136
147
  if (files.length === 0) {
137
148
  console.log('removing: ', folder);
138
- fs.rmdirSync(folder);
149
+ try {
150
+ fs.rmdirSync(folder);
151
+ } catch (error) {
152
+ logger.error(error);
153
+ }
139
154
  return;
140
155
  }
141
156
  }
@@ -174,6 +189,21 @@ try {
174
189
  fs.writeFileSync('b64-image', `data:image/jpg;base64,${fs.readFileSync(process.argv[3]).toString('base64')}`);
175
190
  break;
176
191
 
192
+ case 'get-ip': {
193
+ const response = await axios.get(process.argv[3]);
194
+ logger.info(process.argv[3] + ' IP', response.request.socket.remoteAddress);
195
+ break;
196
+ }
197
+
198
+ case 'clean-env': {
199
+ shellExec(`git checkout package.json`);
200
+ shellExec(`git checkout .env.production`);
201
+ shellExec(`git checkout .env.development`);
202
+ shellExec(`git checkout .env.test`);
203
+ shellExec(`git checkout jsdoc.json`);
204
+ break;
205
+ }
206
+
177
207
  default:
178
208
  break;
179
209
  }
package/conf.js CHANGED
@@ -2,8 +2,14 @@ const DefaultConf = {
2
2
  client: {
3
3
  default: {
4
4
  metadata: {
5
- title: 'Default',
5
+ title: 'Demo App',
6
6
  backgroundImage: './src/client/public/default/assets/background/white0-min.jpg',
7
+ description: 'Web application',
8
+ keywords: ['web', 'app', 'spa', 'demo', 'github-pages'],
9
+ author: 'https://github.com/underpostnet',
10
+ thumbnail: 'android-chrome-384x384.png',
11
+ themeColor: '#ececec',
12
+ pwaAssetsPath: '',
7
13
  },
8
14
  components: {
9
15
  core: [
@@ -168,7 +174,7 @@ const DefaultConf = {
168
174
  },
169
175
  ssr: {
170
176
  Default: {
171
- head: ['PwaDefault', 'Css', 'DefaultScripts'],
177
+ head: ['Seo', 'Pwa', 'Css', 'DefaultScripts', 'Production'],
172
178
  body: ['CacheControl', 'DefaultSplashScreen'],
173
179
  },
174
180
  },
@@ -227,8 +233,6 @@ const DefaultConf = {
227
233
  cron: {
228
234
  ipDaemon: {
229
235
  ip: null,
230
- minutesTimeInterval: 3,
231
- disabled: false,
232
236
  },
233
237
  records: {
234
238
  A: [
@@ -245,6 +249,16 @@ const DefaultConf = {
245
249
  deployGroupId: 'default-group',
246
250
  },
247
251
  ],
252
+ jobs: {
253
+ dns: {
254
+ expression: '* * * * *',
255
+ enabled: true,
256
+ },
257
+ backups: {
258
+ expression: '0 1 * * *',
259
+ enabled: true,
260
+ },
261
+ },
248
262
  },
249
263
  };
250
264
 
@@ -58,7 +58,7 @@ services:
58
58
  cpus: '0.25'
59
59
  memory: 20M
60
60
  labels: # labels in Compose file instead of Dockerfile
61
- engine.version: '2.7.83'
61
+ engine.version: '2.7.91'
62
62
  networks:
63
63
  - load-balancer
64
64
 
package/package.json CHANGED
@@ -2,14 +2,15 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.7.83",
5
+ "version": "2.7.91",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
9
9
  "pm2": "env-cmd -f .env.production pm2 start src/server.js --node-args=\"--max-old-space-size=8192\" --name engine && pm2 logs",
10
10
  "ssl": "env-cmd -f .env.production node bin/ssl",
11
11
  "pm2-delete": "pm2 delete engine",
12
- "build": "node bin/deploy build-full-client --no-warnings",
12
+ "build": "node bin/deploy build-full-client",
13
+ "build-production": "env-cmd -f .env.production node bin/deploy build-full-client",
13
14
  "dev": "env-cmd -f .env.development node src/client.dev --no-warnings",
14
15
  "dev-api": "env-cmd -f .env.development nodemon --watch src --ignore src/client src/api",
15
16
  "docs": "jsdoc -c jsdoc.json",
@@ -95,7 +96,6 @@
95
96
  "marked": "^12.0.2",
96
97
  "mongoose": "^8.0.1",
97
98
  "morgan": "^1.10.0",
98
- "node-cron": "^3.0.3",
99
99
  "nodemailer": "^6.9.9",
100
100
  "nodemon": "^3.0.1",
101
101
  "pathfinding": "^0.4.18",
@@ -1,4 +1,4 @@
1
- import { authMiddleware } from '../../server/auth.js';
1
+ import { adminGuard, authMiddleware } from '../../server/auth.js';
2
2
  import { loggerFactory } from '../../server/logger.js';
3
3
  import { CoreController } from './core.controller.js';
4
4
  import express from 'express';
@@ -7,14 +7,14 @@ const logger = loggerFactory(import.meta);
7
7
 
8
8
  const CoreRouter = (options) => {
9
9
  const router = express.Router();
10
- router.post(`/:id`, async (req, res) => await CoreController.post(req, res, options));
11
- router.post(`/`, async (req, res) => await CoreController.post(req, res, options));
12
- router.get(`/:id`, async (req, res) => await CoreController.get(req, res, options));
13
- router.get(`/`, async (req, res) => await CoreController.get(req, res, options));
14
- router.put(`/:id`, async (req, res) => await CoreController.put(req, res, options));
15
- router.put(`/`, async (req, res) => await CoreController.put(req, res, options));
16
- router.delete(`/:id`, async (req, res) => await CoreController.delete(req, res, options));
17
- router.delete(`/`, async (req, res) => await CoreController.delete(req, res, options));
10
+ router.post(`/:id`, authMiddleware, adminGuard, async (req, res) => await CoreController.post(req, res, options));
11
+ router.post(`/`, authMiddleware, adminGuard, async (req, res) => await CoreController.post(req, res, options));
12
+ router.get(`/:id`, authMiddleware, adminGuard, async (req, res) => await CoreController.get(req, res, options));
13
+ router.get(`/`, authMiddleware, adminGuard, async (req, res) => await CoreController.get(req, res, options));
14
+ router.put(`/:id`, authMiddleware, adminGuard, async (req, res) => await CoreController.put(req, res, options));
15
+ router.put(`/`, authMiddleware, adminGuard, async (req, res) => await CoreController.put(req, res, options));
16
+ router.delete(`/:id`, authMiddleware, adminGuard, async (req, res) => await CoreController.delete(req, res, options));
17
+ router.delete(`/`, authMiddleware, adminGuard, async (req, res) => await CoreController.delete(req, res, options));
18
18
  return router;
19
19
  };
20
20