underpost 2.8.0 → 2.8.6
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/.dockerignore +1 -0
- package/.github/workflows/ghpkg.yml +19 -49
- package/.github/workflows/npmpkg.yml +67 -0
- package/.github/workflows/publish.yml +5 -5
- package/.github/workflows/pwa-microservices-template.page.yml +12 -4
- package/.github/workflows/pwa-microservices-template.test.yml +2 -2
- package/.vscode/extensions.json +17 -71
- package/.vscode/settings.json +20 -4
- package/AUTHORS.md +16 -5
- package/CHANGELOG.md +103 -3
- package/Dockerfile +24 -66
- package/README.md +1 -28
- package/bin/build.js +186 -0
- package/bin/db.js +2 -24
- package/bin/deploy.js +168 -157
- package/bin/file.js +59 -16
- package/bin/hwt.js +0 -10
- package/bin/index.js +201 -61
- package/bin/ssl.js +19 -11
- package/bin/util.js +24 -101
- package/bin/vs.js +26 -2
- package/conf.js +30 -132
- package/docker-compose.yml +1 -1
- package/manifests/deployment/mongo-express/deployment.yaml +60 -0
- package/manifests/deployment/phpmyadmin/deployment.yaml +54 -0
- package/manifests/kind-config-dev.yaml +12 -0
- package/manifests/kind-config.yaml +12 -0
- package/manifests/letsencrypt-prod.yaml +15 -0
- package/manifests/mariadb/config.yaml +10 -0
- package/manifests/mariadb/kustomization.yaml +9 -0
- package/manifests/mariadb/pv.yaml +12 -0
- package/manifests/mariadb/pvc.yaml +10 -0
- package/manifests/mariadb/secret.yaml +8 -0
- package/manifests/mariadb/service.yaml +10 -0
- package/manifests/mariadb/statefulset.yaml +55 -0
- package/manifests/mongodb/backup-access.yaml +16 -0
- package/manifests/mongodb/backup-cronjob.yaml +42 -0
- package/manifests/mongodb/backup-pv-pvc.yaml +22 -0
- package/manifests/mongodb/configmap.yaml +26 -0
- package/manifests/mongodb/headless-service.yaml +10 -0
- package/manifests/mongodb/kustomization.yaml +11 -0
- package/manifests/mongodb/pv-pvc.yaml +23 -0
- package/manifests/mongodb/statefulset.yaml +125 -0
- package/manifests/mongodb-4.4/kustomization.yaml +7 -0
- package/manifests/mongodb-4.4/pv-pvc.yaml +23 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
- package/manifests/valkey/kustomization.yaml +7 -0
- package/manifests/valkey/service.yaml +17 -0
- package/manifests/valkey/statefulset.yaml +39 -0
- package/package.json +133 -134
- package/src/api/core/core.service.js +1 -1
- package/src/api/user/user.model.js +16 -3
- package/src/api/user/user.service.js +1 -1
- package/src/cli/cluster.js +202 -0
- package/src/cli/cron.js +90 -0
- package/src/cli/db.js +212 -0
- package/src/cli/deploy.js +318 -0
- package/src/cli/env.js +52 -0
- package/src/cli/fs.js +149 -0
- package/src/cli/image.js +148 -0
- package/src/cli/repository.js +125 -0
- package/src/cli/script.js +53 -0
- package/src/cli/secrets.js +37 -0
- package/src/cli/test.js +118 -0
- package/src/client/components/core/Account.js +4 -2
- package/src/client/components/core/Auth.js +24 -6
- package/src/client/components/core/CalendarCore.js +127 -50
- package/src/client/components/core/CommonJs.js +282 -19
- package/src/client/components/core/Css.js +2 -1
- package/src/client/components/core/CssCore.js +8 -4
- package/src/client/components/core/Docs.js +1 -1
- package/src/client/components/core/DropDown.js +5 -1
- package/src/client/components/core/Input.js +22 -6
- package/src/client/components/core/JoyStick.js +8 -5
- package/src/client/components/core/LoadingAnimation.js +8 -1
- package/src/client/components/core/Modal.js +47 -18
- package/src/client/components/core/Panel.js +93 -31
- package/src/client/components/core/PanelForm.js +27 -19
- package/src/client/components/core/Scroll.js +1 -0
- package/src/client/components/core/SignUp.js +4 -1
- package/src/client/components/core/Translate.js +61 -9
- package/src/client/components/core/Validator.js +9 -1
- package/src/client/components/core/VanillaJs.js +0 -9
- package/src/client/components/core/Worker.js +34 -31
- package/src/client/public/default/plantuml/client-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-conf.svg +1 -1
- package/src/client/public/default/plantuml/server-schema.svg +1 -1
- package/src/client/public/default/plantuml/ssr-conf.svg +1 -1
- package/src/client/public/default/plantuml/ssr-schema.svg +1 -1
- package/src/client/services/core/core.service.js +15 -8
- package/src/client/services/default/default.management.js +4 -2
- package/src/client/ssr/Render.js +4 -1
- package/src/client/ssr/body/CacheControl.js +2 -2
- package/src/client/ssr/body/DefaultSplashScreen.js +3 -3
- package/src/client/ssr/offline/Maintenance.js +63 -0
- package/src/client/sw/default.sw.js +26 -6
- package/src/db/mongo/MongooseDB.js +29 -1
- package/src/index.js +91 -17
- package/src/runtime/lampp/Lampp.js +1 -13
- package/src/runtime/xampp/Xampp.js +0 -13
- package/src/server/auth.js +3 -3
- package/src/server/backup.js +49 -93
- package/src/server/client-build.js +41 -50
- package/src/server/client-formatted.js +6 -3
- package/src/server/client-icons.js +1 -1
- package/src/server/conf.js +207 -57
- package/src/server/dns.js +30 -55
- package/src/server/downloader.js +0 -8
- package/src/server/logger.js +22 -15
- package/src/server/network.js +17 -43
- package/src/server/process.js +25 -2
- package/src/server/proxy.js +4 -26
- package/src/server/runtime.js +30 -30
- package/src/server/ssl.js +1 -1
- package/src/server/valkey.js +3 -0
- package/test/api.test.js +0 -8
- package/src/dns.js +0 -22
- package/src/server/prompt-optimizer.js +0 -28
- package/startup.js +0 -11
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
SrrComponent = ({
|
|
2
|
-
${
|
|
1
|
+
SrrComponent = ({ backgroundImage, metadata }) => html`
|
|
2
|
+
${backgroundImage
|
|
3
3
|
? html`<style>
|
|
4
4
|
.ssr-background-image {
|
|
5
|
-
background-image: url('${
|
|
5
|
+
background-image: url('${backgroundImage}');
|
|
6
6
|
}
|
|
7
7
|
</style>`
|
|
8
8
|
: metadata?.themeColor
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const s = (el) => document.querySelector(el);
|
|
2
|
+
|
|
3
|
+
const append = (el, html) => s(el).insertAdjacentHTML('beforeend', html);
|
|
4
|
+
|
|
5
|
+
const getLang = () =>
|
|
6
|
+
(localStorage.getItem('lang') || navigator.language || navigator.userLanguage || s('html').lang)
|
|
7
|
+
.slice(0, 2)
|
|
8
|
+
.toLowerCase();
|
|
9
|
+
|
|
10
|
+
const main = () => {
|
|
11
|
+
const Translate = {
|
|
12
|
+
Data: {
|
|
13
|
+
['server-maintenance']: {
|
|
14
|
+
en: "The server is under maintenance <br> we'll be back soon.",
|
|
15
|
+
es: 'El servidor está en mantenimiento <br> volveremos pronto.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
Render: function (id) {
|
|
19
|
+
return this.Data[id][getLang()] ? this.Data[id][getLang()] : this.Data[id]['en'];
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const icon = html`<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 24 24">
|
|
23
|
+
<path
|
|
24
|
+
fill="none"
|
|
25
|
+
stroke="currentColor"
|
|
26
|
+
stroke-linecap="round"
|
|
27
|
+
stroke-linejoin="round"
|
|
28
|
+
stroke-width="2"
|
|
29
|
+
d="M3 7a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v2a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm9 13H6a3 3 0 0 1-3-3v-2a3 3 0 0 1 3-3h10.5m-.5 6a2 2 0 1 0 4 0a2 2 0 1 0-4 0m2-3.5V16m0 4v1.5m3.032-5.25l-1.299.75m-3.463 2l-1.3.75m0-3.5l1.3.75m3.463 2l1.3.75M7 8v.01M7 16v.01"
|
|
30
|
+
/>
|
|
31
|
+
</svg>`;
|
|
32
|
+
|
|
33
|
+
append(
|
|
34
|
+
'body',
|
|
35
|
+
html` <style>
|
|
36
|
+
body {
|
|
37
|
+
font-family: arial;
|
|
38
|
+
font-size: 20px;
|
|
39
|
+
background-color: #d8d8d8;
|
|
40
|
+
color: #333;
|
|
41
|
+
}
|
|
42
|
+
a {
|
|
43
|
+
color: black;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
|
|
47
|
+
<div class="abs center" style="top: 45%">
|
|
48
|
+
${icon}
|
|
49
|
+
<br />
|
|
50
|
+
<br />${Translate.Render('server-maintenance')}
|
|
51
|
+
</div>`,
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
SrrComponent = () => html`<script>
|
|
56
|
+
{
|
|
57
|
+
const s = ${s};
|
|
58
|
+
const append = ${append};
|
|
59
|
+
const getLang = ${getLang};
|
|
60
|
+
const main = ${main};
|
|
61
|
+
window.onload = main;
|
|
62
|
+
}
|
|
63
|
+
</script>`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const PRE_CACHED_RESOURCES = [];
|
|
2
|
-
const CACHE_NAME = 'app-cache';
|
|
3
|
-
const PROXY_PATH = '/';
|
|
1
|
+
const PRE_CACHED_RESOURCES = self.renderPayload?.PRE_CACHED_RESOURCES ? self.renderPayload.PRE_CACHED_RESOURCES : [];
|
|
2
|
+
const CACHE_NAME = self.renderPayload?.CACHE_NAME ? self.renderPayload.CACHE_NAME : 'app-cache';
|
|
3
|
+
const PROXY_PATH = self.renderPayload?.PROXY_PATH ? self.renderPayload.PROXY_PATH : '/';
|
|
4
4
|
self.addEventListener('install', (event) => {
|
|
5
5
|
// Activate right away
|
|
6
6
|
self.skipWaiting();
|
|
@@ -62,15 +62,35 @@ self.addEventListener('fetch', (event) => {
|
|
|
62
62
|
if (!preCachedResponse) throw new Error(error.message);
|
|
63
63
|
return preCachedResponse;
|
|
64
64
|
} catch (error) {
|
|
65
|
-
console.error('Error opening cache for pre cached page',
|
|
65
|
+
console.error('Error opening cache for pre cached page', {
|
|
66
|
+
url: event.request.url,
|
|
67
|
+
error,
|
|
68
|
+
onLine: navigator.onLine,
|
|
69
|
+
});
|
|
66
70
|
try {
|
|
71
|
+
if (!navigator.onLine) {
|
|
72
|
+
if (event.request.method.toUpperCase() === 'GET') {
|
|
73
|
+
const cache = await caches.open(CACHE_NAME);
|
|
74
|
+
const preCachedResponse = await cache.match(
|
|
75
|
+
`${PROXY_PATH === '/' ? '' : PROXY_PATH}/offline/index.html`,
|
|
76
|
+
);
|
|
77
|
+
if (!preCachedResponse) throw new Error(error.message);
|
|
78
|
+
return preCachedResponse;
|
|
79
|
+
}
|
|
80
|
+
const response = new Response(JSON.stringify({ status: 'error', message: 'offline test response' }));
|
|
81
|
+
// response.status = 200;
|
|
82
|
+
response.headers.set('Content-Type', 'application/json');
|
|
83
|
+
return response;
|
|
84
|
+
}
|
|
67
85
|
if (event.request.method.toUpperCase() === 'GET') {
|
|
68
86
|
const cache = await caches.open(CACHE_NAME);
|
|
69
|
-
const preCachedResponse = await cache.match(
|
|
87
|
+
const preCachedResponse = await cache.match(
|
|
88
|
+
`${PROXY_PATH === '/' ? '' : PROXY_PATH}/maintenance/index.html`,
|
|
89
|
+
);
|
|
70
90
|
if (!preCachedResponse) throw new Error(error.message);
|
|
71
91
|
return preCachedResponse;
|
|
72
92
|
}
|
|
73
|
-
const response = new Response(JSON.stringify({ status: 'error', message: '
|
|
93
|
+
const response = new Response(JSON.stringify({ status: 'error', message: 'server in maintenance' }));
|
|
74
94
|
// response.status = 200;
|
|
75
95
|
response.headers.set('Content-Type', 'application/json');
|
|
76
96
|
return response;
|
|
@@ -9,7 +9,12 @@ const MongooseDB = {
|
|
|
9
9
|
connect: async (host, name) => {
|
|
10
10
|
const uri = `${host}/${name}`;
|
|
11
11
|
// logger.info('MongooseDB connect', { host, name, uri });
|
|
12
|
-
return await mongoose
|
|
12
|
+
return await mongoose
|
|
13
|
+
.createConnection(uri, {
|
|
14
|
+
// useNewUrlParser: true,
|
|
15
|
+
// useUnifiedTopology: true,
|
|
16
|
+
})
|
|
17
|
+
.asPromise();
|
|
13
18
|
return new Promise((resolve, reject) =>
|
|
14
19
|
mongoose
|
|
15
20
|
.connect(
|
|
@@ -67,8 +72,27 @@ const MongooseDB = {
|
|
|
67
72
|
shellExec(`sudo rm -r /var/lib/mongodb`);
|
|
68
73
|
// restore lib
|
|
69
74
|
// shellExec(`sudo chown -R mongodb:mongodb /var/lib/mongodb/*`);
|
|
75
|
+
// mongod --repair
|
|
70
76
|
|
|
71
77
|
if (process.argv.includes('legacy')) {
|
|
78
|
+
// TODO:
|
|
79
|
+
if (process.argv.includes('rocky')) {
|
|
80
|
+
// https://github.com/mongodb/mongodb-selinux
|
|
81
|
+
// https://www.mongodb.com/docs/v7.0/tutorial/install-mongodb-enterprise-on-red-hat/
|
|
82
|
+
// https://www.mongodb.com/docs/v6.0/tutorial/install-mongodb-on-red-hat/
|
|
83
|
+
// https://www.mongodb.com/docs/v4.4/tutorial/install-mongodb-on-red-hat/
|
|
84
|
+
// dnf install selinux-policy-devel
|
|
85
|
+
// git clone https://github.com/mongodb/mongodb-selinux
|
|
86
|
+
// cd mongodb-selinux
|
|
87
|
+
// make
|
|
88
|
+
// sudo make install
|
|
89
|
+
// yum list installed | grep mongo
|
|
90
|
+
// sudo yum erase $(rpm -qa | grep mongodb)
|
|
91
|
+
// remove service
|
|
92
|
+
// sudo systemctl reset-failed
|
|
93
|
+
// MongoDB 5.0+ requires a CPU with AVX support
|
|
94
|
+
// check: grep avx /proc/cpuinfo
|
|
95
|
+
}
|
|
72
96
|
logger.info('install legacy 4.4');
|
|
73
97
|
shellExec(`wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -`);
|
|
74
98
|
|
|
@@ -100,9 +124,13 @@ const MongooseDB = {
|
|
|
100
124
|
shellExec(`sudo systemctl unmask mongod`);
|
|
101
125
|
shellExec(`sudo pkill -f mongod`);
|
|
102
126
|
shellExec(`sudo systemctl enable mongod.service`);
|
|
127
|
+
|
|
103
128
|
shellExec(`sudo chown -R mongodb:mongodb /var/lib/mongodb`);
|
|
104
129
|
shellExec(`sudo chown mongodb:mongodb /tmp/mongodb-27017.sock`);
|
|
105
130
|
|
|
131
|
+
shellExec(`sudo chown -R mongod:mongod /var/lib/mongodb`);
|
|
132
|
+
shellExec(`sudo chown mongod:mongod /tmp/mongodb-27017.sock`);
|
|
133
|
+
|
|
106
134
|
logger.info('run server');
|
|
107
135
|
shellExec(`sudo service mongod restart`);
|
|
108
136
|
|
package/src/index.js
CHANGED
|
@@ -4,9 +4,17 @@
|
|
|
4
4
|
* @namespace Underpost
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
import UnderpostCluster from './cli/cluster.js';
|
|
8
|
+
import UnderpostCron from './cli/cron.js';
|
|
9
|
+
import UnderpostDB from './cli/db.js';
|
|
10
|
+
import UnderpostDeploy from './cli/deploy.js';
|
|
11
|
+
import UnderpostRootEnv from './cli/env.js';
|
|
12
|
+
import UnderpostFileStorage from './cli/fs.js';
|
|
13
|
+
import UnderpostImage from './cli/image.js';
|
|
14
|
+
import UnderpostRepository from './cli/repository.js';
|
|
15
|
+
import UnderpostScript from './cli/script.js';
|
|
16
|
+
import UnderpostSecret from './cli/secrets.js';
|
|
17
|
+
import UnderpostTest from './cli/test.js';
|
|
10
18
|
|
|
11
19
|
/**
|
|
12
20
|
* Underpost main module methods
|
|
@@ -14,24 +22,90 @@ const logger = loggerFactory(import.meta);
|
|
|
14
22
|
* @memberof Underpost
|
|
15
23
|
*/
|
|
16
24
|
class Underpost {
|
|
17
|
-
constructor() {}
|
|
18
|
-
|
|
19
25
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
* Underpost engine version
|
|
27
|
+
* @static
|
|
28
|
+
* @type {String}
|
|
29
|
+
* @memberof Underpost
|
|
30
|
+
*/
|
|
31
|
+
static version = 'v2.8.6';
|
|
32
|
+
/**
|
|
33
|
+
* Repository cli API
|
|
27
34
|
* @static
|
|
28
|
-
* @
|
|
29
|
-
* @returns {Promise<void>}
|
|
35
|
+
* @type {UnderpostRepository.API}
|
|
30
36
|
* @memberof Underpost
|
|
31
37
|
*/
|
|
32
|
-
static
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
static repo = UnderpostRepository.API;
|
|
39
|
+
/**
|
|
40
|
+
* Root Env cli API
|
|
41
|
+
* @static
|
|
42
|
+
* @type {UnderpostRootEnv.API}
|
|
43
|
+
* @memberof Underpost
|
|
44
|
+
*/
|
|
45
|
+
static env = UnderpostRootEnv.API;
|
|
46
|
+
/**
|
|
47
|
+
* Test cli API
|
|
48
|
+
* @static
|
|
49
|
+
* @type {UnderpostTest.API}
|
|
50
|
+
* @memberof Underpost
|
|
51
|
+
*/
|
|
52
|
+
static test = UnderpostTest.API;
|
|
53
|
+
/**
|
|
54
|
+
* Cluster cli API
|
|
55
|
+
* @static
|
|
56
|
+
* @type {UnderpostCluster.API}
|
|
57
|
+
* @memberof Underpost
|
|
58
|
+
*/
|
|
59
|
+
static cluster = UnderpostCluster.API;
|
|
60
|
+
/**
|
|
61
|
+
* Image cli API
|
|
62
|
+
* @static
|
|
63
|
+
* @type {UnderpostImage.API}
|
|
64
|
+
* @memberof Underpost
|
|
65
|
+
*/
|
|
66
|
+
static image = UnderpostImage.API;
|
|
67
|
+
/**
|
|
68
|
+
* Secrets cli API
|
|
69
|
+
* @static
|
|
70
|
+
* @type {UnderpostSecret.API}
|
|
71
|
+
* @memberof Underpost
|
|
72
|
+
*/
|
|
73
|
+
static secret = UnderpostSecret.API;
|
|
74
|
+
/**
|
|
75
|
+
* Scripts cli API
|
|
76
|
+
* @static
|
|
77
|
+
* @type {UnderpostScript.API}
|
|
78
|
+
* @memberof Underpost
|
|
79
|
+
*/
|
|
80
|
+
static script = UnderpostScript.API;
|
|
81
|
+
/**
|
|
82
|
+
* Database cli API
|
|
83
|
+
* @static
|
|
84
|
+
* @type {UnderpostDB.API}
|
|
85
|
+
* @memberof Underpost
|
|
86
|
+
*/
|
|
87
|
+
static db = UnderpostDB.API;
|
|
88
|
+
/**
|
|
89
|
+
* Deployment cli API
|
|
90
|
+
* @static
|
|
91
|
+
* @type {UnderpostDeploy.API}
|
|
92
|
+
* @memberof Underpost
|
|
93
|
+
*/
|
|
94
|
+
static deploy = UnderpostDeploy.API;
|
|
95
|
+
/**
|
|
96
|
+
* Cron cli API
|
|
97
|
+
* @static
|
|
98
|
+
* @type {UnderpostCron.API}
|
|
99
|
+
* @memberof Underpost
|
|
100
|
+
*/
|
|
101
|
+
static cron = UnderpostCron.API;
|
|
102
|
+
/**
|
|
103
|
+
* File Storage cli API
|
|
104
|
+
* @static
|
|
105
|
+
* @type {UnderpostFileStorage.API}
|
|
106
|
+
* @memberof UnderpostFileStorage
|
|
107
|
+
*/
|
|
108
|
+
static fs = UnderpostFileStorage.API;
|
|
35
109
|
}
|
|
36
110
|
|
|
37
111
|
const up = Underpost;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
|
-
import { network } from '../../server/network.js';
|
|
3
2
|
import { shellCd, shellExec } from '../../server/process.js';
|
|
4
3
|
import { timer } from '../../client/components/core/CommonJs.js';
|
|
5
4
|
import { loggerFactory } from '../../server/logger.js';
|
|
@@ -39,20 +38,9 @@ const Lampp = {
|
|
|
39
38
|
);
|
|
40
39
|
|
|
41
40
|
shellExec(cmd);
|
|
42
|
-
await network.port.portClean(3306);
|
|
43
|
-
for (const port of this.ports) await network.port.portClean(port);
|
|
44
41
|
cmd = `sudo /opt/lampp/lampp start`;
|
|
45
42
|
if (this.router) fs.writeFileSync(`./tmp/lampp-router.conf`, this.router, 'utf-8');
|
|
46
|
-
shellExec(cmd
|
|
47
|
-
if (options && options.daemon) this.daemon();
|
|
48
|
-
},
|
|
49
|
-
daemon: async function () {
|
|
50
|
-
await timer(1000 * 60 * 2); // 2 minutes
|
|
51
|
-
for (const port of this.ports) {
|
|
52
|
-
const [portStatus] = await network.port.status([port]);
|
|
53
|
-
if (!portStatus.open) return await this.initService();
|
|
54
|
-
}
|
|
55
|
-
this.daemon();
|
|
43
|
+
shellExec(cmd);
|
|
56
44
|
},
|
|
57
45
|
enabled: () => fs.existsSync(`/opt/lampp/apache2/conf/httpd.conf`),
|
|
58
46
|
appendRouter: function (render) {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
|
-
import { network } from '../../server/network.js';
|
|
3
2
|
import { shellExec } from '../../server/process.js';
|
|
4
|
-
import { timer } from '../../client/components/core/CommonJs.js';
|
|
5
3
|
|
|
6
4
|
const Xampp = {
|
|
7
5
|
ports: [],
|
|
@@ -16,20 +14,9 @@ const Xampp = {
|
|
|
16
14
|
fs.writeFileSync(`C:/xampp/apache/conf/extra/httpd-ssl.conf`, this.router || '', 'utf8');
|
|
17
15
|
cmd = `C:/xampp/xampp_stop.exe`;
|
|
18
16
|
shellExec(cmd);
|
|
19
|
-
await network.port.portClean(3306);
|
|
20
|
-
for (const port of this.ports) await network.port.portClean(port);
|
|
21
17
|
cmd = `C:/xampp/xampp_start.exe`;
|
|
22
18
|
if (this.router) fs.writeFileSync(`./tmp/xampp-router.conf`, this.router, 'utf-8');
|
|
23
19
|
shellExec(cmd);
|
|
24
|
-
if (options && options.daemon) this.daemon();
|
|
25
|
-
},
|
|
26
|
-
daemon: async function () {
|
|
27
|
-
await timer(1000 * 60 * 2); // 2 minutes
|
|
28
|
-
for (const port of this.ports) {
|
|
29
|
-
const [portStatus] = await network.port.status([port]);
|
|
30
|
-
if (!portStatus.open) return await this.initService();
|
|
31
|
-
}
|
|
32
|
-
this.daemon();
|
|
33
20
|
},
|
|
34
21
|
enabled: () => fs.existsSync(`C:/xampp/apache/conf/httpd.conf`),
|
|
35
22
|
appendRouter: function (render) {
|
package/src/server/auth.js
CHANGED
|
@@ -9,7 +9,7 @@ import jwt from 'jsonwebtoken';
|
|
|
9
9
|
import { loggerFactory } from './logger.js';
|
|
10
10
|
import crypto from 'crypto';
|
|
11
11
|
import { userRoleEnum } from '../api/user/user.model.js';
|
|
12
|
-
import { validatePassword } from '../client/components/core/CommonJs.js';
|
|
12
|
+
import { commonAdminGuard, commonModeratorGuard, validatePassword } from '../client/components/core/CommonJs.js';
|
|
13
13
|
|
|
14
14
|
dotenv.config();
|
|
15
15
|
|
|
@@ -162,7 +162,7 @@ const authMiddleware = (req, res, next) => {
|
|
|
162
162
|
*/
|
|
163
163
|
const adminGuard = (req, res, next) => {
|
|
164
164
|
try {
|
|
165
|
-
if (!(
|
|
165
|
+
if (!commonAdminGuard(req.auth.user.role))
|
|
166
166
|
return res.status(403).json({ status: 'error', message: 'Insufficient permission' });
|
|
167
167
|
return next();
|
|
168
168
|
} catch (error) {
|
|
@@ -194,7 +194,7 @@ const adminGuard = (req, res, next) => {
|
|
|
194
194
|
*/
|
|
195
195
|
const moderatorGuard = (req, res, next) => {
|
|
196
196
|
try {
|
|
197
|
-
if (!(
|
|
197
|
+
if (!commonModeratorGuard(req.auth.user.role))
|
|
198
198
|
return res.status(403).json({ status: 'error', message: 'Insufficient permission' });
|
|
199
199
|
return next();
|
|
200
200
|
} catch (error) {
|
package/src/server/backup.js
CHANGED
|
@@ -1,120 +1,76 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import { loggerFactory } from './logger.js';
|
|
3
|
-
import {
|
|
4
|
-
import { getCronBackUpFolder
|
|
3
|
+
import { shellExec } from './process.js';
|
|
4
|
+
import { getCronBackUpFolder } from './conf.js';
|
|
5
5
|
import dotenv from 'dotenv';
|
|
6
6
|
|
|
7
7
|
dotenv.config();
|
|
8
8
|
|
|
9
9
|
const logger = loggerFactory(import.meta);
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
|
|
11
|
+
class BackUp {
|
|
12
|
+
static callback = async function (deployList, options = { itc: false, git: false }) {
|
|
13
|
+
if ((!deployList || deployList === 'dd') && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
14
|
+
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
logger.info('init backups callback', deployList);
|
|
17
|
+
await logger.setUpInfo();
|
|
18
|
+
const currentDate = new Date().getTime();
|
|
19
|
+
const maxBackupRetention = 5;
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
if (!fs.existsSync('./engine-private/cron-backups'))
|
|
22
|
+
fs.mkdirSync('./engine-private/cron-backups', { recursive: true });
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
for (const _deployId of deployList.split(',')) {
|
|
25
|
+
const deployId = _deployId.trim();
|
|
26
|
+
if (!deployId) continue;
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (!fs.existsSync('./engine-private/cron-backups'))
|
|
29
|
-
fs.mkdirSync('./engine-private/cron-backups', { recursive: true });
|
|
30
|
-
|
|
31
|
-
for (const deployGroupData of backups) {
|
|
32
|
-
const { deployGroupId } = deployGroupData;
|
|
33
|
-
const dataDeploy = getDataDeploy({ deployGroupId });
|
|
34
|
-
|
|
35
|
-
for (const deployObj of dataDeploy) {
|
|
36
|
-
const { deployId, replicaHost } = deployObj;
|
|
37
|
-
|
|
38
|
-
if (replicaHost) continue;
|
|
39
|
-
|
|
40
|
-
const confServer = JSON.parse(
|
|
41
|
-
fs.existsSync(`./engine-private/replica/${deployId}/conf.server.json`)
|
|
42
|
-
? fs.readFileSync(`./engine-private/replica/${deployId}/conf.server.json`, 'utf8')
|
|
43
|
-
: fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
for (const host of Object.keys(confServer))
|
|
47
|
-
for (const path of Object.keys(confServer[host])) {
|
|
48
|
-
// retention policy
|
|
49
|
-
let { db, backupFrequency, maxBackupRetention, singleReplica, wp, git, directory } =
|
|
50
|
-
confServer[host][path];
|
|
51
|
-
|
|
52
|
-
if (!db || singleReplica) continue;
|
|
53
|
-
|
|
54
|
-
if (!backupFrequency) backupFrequency = 'daily';
|
|
55
|
-
if (!maxBackupRetention) maxBackupRetention = 5;
|
|
56
|
-
|
|
57
|
-
const backUpPath = `${process.cwd()}/engine-private/cron-backups/${getCronBackUpFolder(host, path)}`;
|
|
58
|
-
if (!fs.existsSync(backUpPath)) fs.mkdirSync(`${backUpPath}`, { recursive: true });
|
|
59
|
-
// .isDirectory()
|
|
60
|
-
const files = await fs.readdir(backUpPath, { withFileTypes: true });
|
|
61
|
-
|
|
62
|
-
const currentBackupsDirs = files
|
|
63
|
-
.map((fileObj) => parseInt(fileObj.name))
|
|
64
|
-
.sort((a, b) => a - b)
|
|
65
|
-
.reverse();
|
|
28
|
+
if (!(options.itc === true)) {
|
|
29
|
+
shellExec(`node bin db ${options.git ? '--git ' : ''}--export ${deployId}`);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
66
32
|
|
|
67
|
-
|
|
68
|
-
case 'daily':
|
|
33
|
+
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
|
|
69
34
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
35
|
+
for (const host of Object.keys(confServer))
|
|
36
|
+
for (const path of Object.keys(confServer[host])) {
|
|
37
|
+
// retention policy
|
|
38
|
+
const { db } = confServer[host][path];
|
|
39
|
+
if (!db) continue;
|
|
40
|
+
logger.info('Init backup', { host, path, db });
|
|
74
41
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
42
|
+
const backUpPath = `${process.cwd()}/engine-private/cron-backups/${getCronBackUpFolder(host, path)}`;
|
|
43
|
+
if (!fs.existsSync(backUpPath)) fs.mkdirSync(`${backUpPath}`, { recursive: true });
|
|
44
|
+
// .isDirectory()
|
|
45
|
+
const files = await fs.readdir(backUpPath, { withFileTypes: true });
|
|
80
46
|
|
|
81
|
-
|
|
47
|
+
const currentBackupsDirs = files
|
|
48
|
+
.map((fileObj) => parseInt(fileObj.name))
|
|
49
|
+
.sort((a, b) => a - b)
|
|
50
|
+
.reverse();
|
|
82
51
|
|
|
83
|
-
|
|
52
|
+
for (const retentionPath of currentBackupsDirs.filter((t, i) => i >= maxBackupRetention - 1)) {
|
|
53
|
+
const removePathRetention = `${backUpPath}/${retentionPath}`;
|
|
54
|
+
logger.info('Remove backup folder', removePathRetention);
|
|
55
|
+
fs.removeSync(removePathRetention);
|
|
56
|
+
}
|
|
84
57
|
|
|
85
|
-
|
|
86
|
-
const repoUrl = `https://${process.env.GITHUB_TOKEN}@github.com/${process.env.GITHUB_USERNAME}/${git
|
|
87
|
-
.split('/')
|
|
88
|
-
.pop()}.git`;
|
|
58
|
+
fs.mkdirSync(`${backUpPath}/${currentDate}`, { recursive: true });
|
|
89
59
|
|
|
90
|
-
|
|
91
|
-
`cd ${directory}` +
|
|
92
|
-
` && git pull ${repoUrl}` +
|
|
93
|
-
` && git add . && git commit -m "backup ${new Date().toLocaleDateString()}"` +
|
|
94
|
-
` && git push ${repoUrl}`,
|
|
95
|
-
{
|
|
96
|
-
disableLog: true,
|
|
97
|
-
},
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
60
|
+
shellExec(`node bin/db ${host}${path} export ${deployId} ${backUpPath}/${currentDate}`);
|
|
101
61
|
}
|
|
102
|
-
}
|
|
103
62
|
shellExec(
|
|
104
63
|
`cd ./engine-private/cron-backups` +
|
|
105
|
-
` &&
|
|
106
|
-
` && git add
|
|
107
|
-
` &&
|
|
64
|
+
` && underpost pull . underpostnet/cron-backups` +
|
|
65
|
+
` && git add .` +
|
|
66
|
+
` && underpost cmt . backup cron-job '${new Date().toLocaleDateString()}'` +
|
|
67
|
+
` && underpost push . underpostnet/cron-backups`,
|
|
108
68
|
{
|
|
109
69
|
disableLog: true,
|
|
110
70
|
},
|
|
111
71
|
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return Callback;
|
|
116
|
-
},
|
|
117
|
-
Callback: async function (params) {},
|
|
118
|
-
};
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
119
75
|
|
|
120
|
-
export
|
|
76
|
+
export default BackUp;
|