underpost 2.6.2

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 (269) hide show
  1. package/.dockerignore +14 -0
  2. package/.env.development +8 -0
  3. package/.env.production +8 -0
  4. package/.env.test +8 -0
  5. package/.nycrc +9 -0
  6. package/.prettierignore +13 -0
  7. package/.prettierrc +9 -0
  8. package/.vscode/extensions.json +72 -0
  9. package/.vscode/settings.json +99 -0
  10. package/Dockerfile +88 -0
  11. package/LICENSE +21 -0
  12. package/README.md +51 -0
  13. package/bin/db.js +119 -0
  14. package/bin/deploy.js +600 -0
  15. package/bin/dns.js +1 -0
  16. package/bin/file.js +92 -0
  17. package/bin/help.js +110 -0
  18. package/bin/index.js +29 -0
  19. package/bin/install.js +357 -0
  20. package/bin/shortcut.js +44 -0
  21. package/bin/ssl.js +61 -0
  22. package/bin/util.js +182 -0
  23. package/bin/vs.js +35 -0
  24. package/conf.js +244 -0
  25. package/docker-compose.yml +67 -0
  26. package/jsconfig.json +7 -0
  27. package/jsdoc.json +32 -0
  28. package/nodemon.json +6 -0
  29. package/package.json +128 -0
  30. package/prometheus.yml +36 -0
  31. package/setup.sh +25 -0
  32. package/src/api/core/core.controller.js +69 -0
  33. package/src/api/core/core.model.js +11 -0
  34. package/src/api/core/core.router.js +23 -0
  35. package/src/api/core/core.service.js +29 -0
  36. package/src/api/crypto/crypto.controller.js +51 -0
  37. package/src/api/crypto/crypto.model.js +23 -0
  38. package/src/api/crypto/crypto.router.js +20 -0
  39. package/src/api/crypto/crypto.service.js +64 -0
  40. package/src/api/default/default.controller.js +69 -0
  41. package/src/api/default/default.model.js +20 -0
  42. package/src/api/default/default.router.js +23 -0
  43. package/src/api/default/default.service.js +31 -0
  44. package/src/api/file/file.controller.js +51 -0
  45. package/src/api/file/file.model.js +19 -0
  46. package/src/api/file/file.router.js +20 -0
  47. package/src/api/file/file.service.js +70 -0
  48. package/src/api/instance/instance.controller.js +69 -0
  49. package/src/api/instance/instance.model.js +36 -0
  50. package/src/api/instance/instance.router.js +33 -0
  51. package/src/api/instance/instance.service.js +48 -0
  52. package/src/api/test/test.controller.js +59 -0
  53. package/src/api/test/test.model.js +14 -0
  54. package/src/api/test/test.router.js +21 -0
  55. package/src/api/test/test.service.js +35 -0
  56. package/src/api/user/user.controller.js +70 -0
  57. package/src/api/user/user.model.js +65 -0
  58. package/src/api/user/user.router.js +345 -0
  59. package/src/api/user/user.service.js +479 -0
  60. package/src/api.js +23 -0
  61. package/src/client/Default.index.js +40 -0
  62. package/src/client/components/core/Account.js +290 -0
  63. package/src/client/components/core/AgGrid.js +160 -0
  64. package/src/client/components/core/Auth.js +19 -0
  65. package/src/client/components/core/Badge.js +32 -0
  66. package/src/client/components/core/BlockChain.js +41 -0
  67. package/src/client/components/core/Blog.js +9 -0
  68. package/src/client/components/core/BtnIcon.js +91 -0
  69. package/src/client/components/core/CalendarCore.js +319 -0
  70. package/src/client/components/core/Chat.js +64 -0
  71. package/src/client/components/core/ColorPalette.js +5267 -0
  72. package/src/client/components/core/CommonJs.js +708 -0
  73. package/src/client/components/core/Content.js +49 -0
  74. package/src/client/components/core/Css.js +1027 -0
  75. package/src/client/components/core/CssCore.js +792 -0
  76. package/src/client/components/core/D3Chart.js +44 -0
  77. package/src/client/components/core/Docs.js +130 -0
  78. package/src/client/components/core/DropDown.js +164 -0
  79. package/src/client/components/core/EventsUI.js +54 -0
  80. package/src/client/components/core/FileExplorer.js +624 -0
  81. package/src/client/components/core/FullScreen.js +45 -0
  82. package/src/client/components/core/Input.js +259 -0
  83. package/src/client/components/core/JoyStick.js +77 -0
  84. package/src/client/components/core/Keyboard.js +73 -0
  85. package/src/client/components/core/LoadingAnimation.js +157 -0
  86. package/src/client/components/core/LogIn.js +181 -0
  87. package/src/client/components/core/LogOut.js +52 -0
  88. package/src/client/components/core/Logger.js +26 -0
  89. package/src/client/components/core/Modal.js +1596 -0
  90. package/src/client/components/core/NotificationManager.js +84 -0
  91. package/src/client/components/core/Panel.js +413 -0
  92. package/src/client/components/core/Polyhedron.js +162 -0
  93. package/src/client/components/core/Recover.js +204 -0
  94. package/src/client/components/core/Responsive.js +53 -0
  95. package/src/client/components/core/RichText.js +27 -0
  96. package/src/client/components/core/Router.js +77 -0
  97. package/src/client/components/core/SignUp.js +125 -0
  98. package/src/client/components/core/SocketIo.js +72 -0
  99. package/src/client/components/core/Stream.js +113 -0
  100. package/src/client/components/core/ToggleSwitch.js +87 -0
  101. package/src/client/components/core/ToolTip.js +26 -0
  102. package/src/client/components/core/Translate.js +408 -0
  103. package/src/client/components/core/Validator.js +100 -0
  104. package/src/client/components/core/VanillaJs.js +454 -0
  105. package/src/client/components/core/Wallet.js +106 -0
  106. package/src/client/components/core/Webhook.js +25 -0
  107. package/src/client/components/core/Worker.js +272 -0
  108. package/src/client/components/default/CommonDefault.js +29 -0
  109. package/src/client/components/default/CssDefault.js +13 -0
  110. package/src/client/components/default/ElementsDefault.js +38 -0
  111. package/src/client/components/default/LogInDefault.js +41 -0
  112. package/src/client/components/default/LogOutDefault.js +28 -0
  113. package/src/client/components/default/MenuDefault.js +389 -0
  114. package/src/client/components/default/RoutesDefault.js +48 -0
  115. package/src/client/components/default/SettingsDefault.js +16 -0
  116. package/src/client/components/default/SignUpDefault.js +9 -0
  117. package/src/client/components/default/SocketIoDefault.js +54 -0
  118. package/src/client/components/default/TranslateDefault.js +7 -0
  119. package/src/client/public/default/android-chrome-144x144.png +0 -0
  120. package/src/client/public/default/android-chrome-192x192.png +0 -0
  121. package/src/client/public/default/android-chrome-256x256.png +0 -0
  122. package/src/client/public/default/android-chrome-36x36.png +0 -0
  123. package/src/client/public/default/android-chrome-384x384.png +0 -0
  124. package/src/client/public/default/android-chrome-48x48.png +0 -0
  125. package/src/client/public/default/android-chrome-512x512.png +0 -0
  126. package/src/client/public/default/android-chrome-72x72.png +0 -0
  127. package/src/client/public/default/android-chrome-96x96.png +0 -0
  128. package/src/client/public/default/apple-touch-icon-1024x1024.png +0 -0
  129. package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
  130. package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
  131. package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
  132. package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
  133. package/src/client/public/default/apple-touch-icon-167x167.png +0 -0
  134. package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
  135. package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
  136. package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
  137. package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
  138. package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
  139. package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
  140. package/src/client/public/default/apple-touch-icon.png +0 -0
  141. package/src/client/public/default/apple-touch-startup-image-1125x2436.png +0 -0
  142. package/src/client/public/default/apple-touch-startup-image-1136x640.png +0 -0
  143. package/src/client/public/default/apple-touch-startup-image-1170x2532.png +0 -0
  144. package/src/client/public/default/apple-touch-startup-image-1179x2556.png +0 -0
  145. package/src/client/public/default/apple-touch-startup-image-1242x2208.png +0 -0
  146. package/src/client/public/default/apple-touch-startup-image-1242x2688.png +0 -0
  147. package/src/client/public/default/apple-touch-startup-image-1284x2778.png +0 -0
  148. package/src/client/public/default/apple-touch-startup-image-1290x2796.png +0 -0
  149. package/src/client/public/default/apple-touch-startup-image-1334x750.png +0 -0
  150. package/src/client/public/default/apple-touch-startup-image-1488x2266.png +0 -0
  151. package/src/client/public/default/apple-touch-startup-image-1536x2048.png +0 -0
  152. package/src/client/public/default/apple-touch-startup-image-1620x2160.png +0 -0
  153. package/src/client/public/default/apple-touch-startup-image-1640x2160.png +0 -0
  154. package/src/client/public/default/apple-touch-startup-image-1668x2224.png +0 -0
  155. package/src/client/public/default/apple-touch-startup-image-1668x2388.png +0 -0
  156. package/src/client/public/default/apple-touch-startup-image-1792x828.png +0 -0
  157. package/src/client/public/default/apple-touch-startup-image-2048x1536.png +0 -0
  158. package/src/client/public/default/apple-touch-startup-image-2048x2732.png +0 -0
  159. package/src/client/public/default/apple-touch-startup-image-2160x1620.png +0 -0
  160. package/src/client/public/default/apple-touch-startup-image-2160x1640.png +0 -0
  161. package/src/client/public/default/apple-touch-startup-image-2208x1242.png +0 -0
  162. package/src/client/public/default/apple-touch-startup-image-2224x1668.png +0 -0
  163. package/src/client/public/default/apple-touch-startup-image-2266x1488.png +0 -0
  164. package/src/client/public/default/apple-touch-startup-image-2388x1668.png +0 -0
  165. package/src/client/public/default/apple-touch-startup-image-2436x1125.png +0 -0
  166. package/src/client/public/default/apple-touch-startup-image-2532x1170.png +0 -0
  167. package/src/client/public/default/apple-touch-startup-image-2556x1179.png +0 -0
  168. package/src/client/public/default/apple-touch-startup-image-2688x1242.png +0 -0
  169. package/src/client/public/default/apple-touch-startup-image-2732x2048.png +0 -0
  170. package/src/client/public/default/apple-touch-startup-image-2778x1284.png +0 -0
  171. package/src/client/public/default/apple-touch-startup-image-2796x1290.png +0 -0
  172. package/src/client/public/default/apple-touch-startup-image-640x1136.png +0 -0
  173. package/src/client/public/default/apple-touch-startup-image-750x1334.png +0 -0
  174. package/src/client/public/default/apple-touch-startup-image-828x1792.png +0 -0
  175. package/src/client/public/default/assets/background/white.jpg +0 -0
  176. package/src/client/public/default/assets/background/white0-min.jpg +0 -0
  177. package/src/client/public/default/assets/background/white0.jpg +0 -0
  178. package/src/client/public/default/assets/logo/base-icon.png +0 -0
  179. package/src/client/public/default/browserconfig.xml +12 -0
  180. package/src/client/public/default/favicon-16x16.png +0 -0
  181. package/src/client/public/default/favicon-32x32.png +0 -0
  182. package/src/client/public/default/favicon-48x48.png +0 -0
  183. package/src/client/public/default/favicon.ico +0 -0
  184. package/src/client/public/default/manifest.webmanifest +69 -0
  185. package/src/client/public/default/mstile-144x144.png +0 -0
  186. package/src/client/public/default/mstile-150x150.png +0 -0
  187. package/src/client/public/default/mstile-310x150.png +0 -0
  188. package/src/client/public/default/mstile-310x310.png +0 -0
  189. package/src/client/public/default/mstile-70x70.png +0 -0
  190. package/src/client/public/default/sitemap +148 -0
  191. package/src/client/public/default/yandex-browser-50x50.png +0 -0
  192. package/src/client/public/default/yandex-browser-manifest.json +9 -0
  193. package/src/client/public/doc/favicon.ico +0 -0
  194. package/src/client/public/doc/sitemap +148 -0
  195. package/src/client/public/test/favicon.ico +0 -0
  196. package/src/client/public/test/sitemap +148 -0
  197. package/src/client/services/core/core.service.js +152 -0
  198. package/src/client/services/crypto/crypto.service.js +70 -0
  199. package/src/client/services/default/default.management.js +345 -0
  200. package/src/client/services/default/default.service.js +89 -0
  201. package/src/client/services/file/file.service.js +70 -0
  202. package/src/client/services/instance/instance.management.js +74 -0
  203. package/src/client/services/instance/instance.service.js +89 -0
  204. package/src/client/services/test/test.service.js +70 -0
  205. package/src/client/services/user/user.management.js +50 -0
  206. package/src/client/services/user/user.service.js +89 -0
  207. package/src/client/ssr/Render.js +16 -0
  208. package/src/client/ssr/body-components/CacheControl.js +113 -0
  209. package/src/client/ssr/body-components/DefaultSplashScreen.js +79 -0
  210. package/src/client/ssr/email-components/DefaultRecoverEmail.js +21 -0
  211. package/src/client/ssr/email-components/DefaultVerifyEmail.js +17 -0
  212. package/src/client/ssr/head-components/Css.js +241 -0
  213. package/src/client/ssr/head-components/DefaultScripts.js +3 -0
  214. package/src/client/ssr/head-components/Microdata.js +11 -0
  215. package/src/client/ssr/head-components/Production.js +1 -0
  216. package/src/client/ssr/head-components/PwaDefault.js +60 -0
  217. package/src/client/ssr/head-components/Seo.js +14 -0
  218. package/src/client/sw/default.sw.js +201 -0
  219. package/src/client/sw/template.sw.js +84 -0
  220. package/src/client.build.js +22 -0
  221. package/src/client.dev.js +21 -0
  222. package/src/cron.js +25 -0
  223. package/src/db/DataBaseProvider.js +34 -0
  224. package/src/db/mariadb/MariaDB.js +33 -0
  225. package/src/db/mongo/MongooseDB.js +46 -0
  226. package/src/dns.js +22 -0
  227. package/src/mailer/EmailRender.js +69 -0
  228. package/src/mailer/MailerProvider.js +96 -0
  229. package/src/proxy.js +22 -0
  230. package/src/runtime/lampp/Lampp.js +44 -0
  231. package/src/runtime/nginx/Nginx.js +3 -0
  232. package/src/runtime/xampp/Xampp.js +49 -0
  233. package/src/server/auth.js +204 -0
  234. package/src/server/backup.js +83 -0
  235. package/src/server/client-build-live.js +72 -0
  236. package/src/server/client-build.js +688 -0
  237. package/src/server/client-dev-server.js +58 -0
  238. package/src/server/client-formatted.js +48 -0
  239. package/src/server/client-icons.js +150 -0
  240. package/src/server/conf.js +611 -0
  241. package/src/server/dns.js +87 -0
  242. package/src/server/downloader.js +42 -0
  243. package/src/server/logger.js +135 -0
  244. package/src/server/network.js +122 -0
  245. package/src/server/peer.js +33 -0
  246. package/src/server/process.js +66 -0
  247. package/src/server/proxy.js +118 -0
  248. package/src/server/runtime.js +393 -0
  249. package/src/server/ssl.js +107 -0
  250. package/src/server.js +25 -0
  251. package/src/ws/IoInterface.js +45 -0
  252. package/src/ws/IoServer.js +39 -0
  253. package/src/ws/core/channels/core.ws.chat.js +23 -0
  254. package/src/ws/core/channels/core.ws.mailer.js +35 -0
  255. package/src/ws/core/channels/core.ws.stream.js +31 -0
  256. package/src/ws/core/core.ws.connection.js +28 -0
  257. package/src/ws/core/core.ws.emit.js +14 -0
  258. package/src/ws/core/core.ws.server.js +24 -0
  259. package/src/ws/core/management/core.ws.chat.js +8 -0
  260. package/src/ws/core/management/core.ws.mailer.js +16 -0
  261. package/src/ws/core/management/core.ws.stream.js +8 -0
  262. package/src/ws/default/channels/default.ws.main.js +16 -0
  263. package/src/ws/default/default.ws.connection.js +22 -0
  264. package/src/ws/default/default.ws.emit.js +14 -0
  265. package/src/ws/default/default.ws.server.js +20 -0
  266. package/src/ws/default/management/default.ws.main.js +8 -0
  267. package/startup.js +11 -0
  268. package/supervisord-openssh-server.conf +5 -0
  269. package/test/api.test.js +60 -0
package/src/cron.js ADDED
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ // https://nodejs.org/api
4
+ // https://expressjs.com/en/4x/api.html
5
+
6
+ import dotenv from 'dotenv';
7
+ import { loggerFactory } from './server/logger.js';
8
+ import { Dns } from './server/dns.js';
9
+ import { ProcessController } from './server/process.js';
10
+ import { Config } from './server/conf.js';
11
+ import { BackUpManagement } from './server/backup.js';
12
+
13
+ dotenv.config();
14
+
15
+ await Config.build();
16
+
17
+ const logger = loggerFactory(import.meta);
18
+
19
+ await logger.setUpInfo();
20
+
21
+ await Dns.InitIpDaemon();
22
+
23
+ await BackUpManagement.Init();
24
+
25
+ ProcessController.init(logger);
@@ -0,0 +1,34 @@
1
+ import { MongooseDB } from './mongo/MongooseDB.js';
2
+ import { loggerFactory } from '../server/logger.js';
3
+
4
+ const logger = loggerFactory(import.meta);
5
+
6
+ const DataBaseProvider = {
7
+ instance: {},
8
+ load: async function (options = { apis: [], host: '', path: '', db: {} }) {
9
+ try {
10
+ const { apis, host, path, db } = options;
11
+
12
+ if (!this.instance[`${host}${path}`]) this.instance[`${host}${path}`] = {};
13
+
14
+ if (!db || this.instance[`${host}${path}`][db.provider]) return;
15
+
16
+ // logger.info(`Load ${db.provider} provider`, `${host}${path}`);
17
+ switch (db.provider) {
18
+ case 'mongoose':
19
+ {
20
+ const conn = await MongooseDB.connect(db.host, db.name);
21
+ this.instance[`${host}${path}`][db.provider] = await MongooseDB.loadModels({ conn, apis });
22
+ }
23
+ break;
24
+ default:
25
+ break;
26
+ }
27
+ return this.instance[`${host}${path}`][db.provider];
28
+ } catch (error) {
29
+ logger.error(error, { error: error.stack, options });
30
+ return undefined;
31
+ }
32
+ },
33
+ };
34
+ export { DataBaseProvider };
@@ -0,0 +1,33 @@
1
+ import mariadb from 'mariadb';
2
+
3
+ import { loggerFactory } from '../../server/logger.js';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ const MariaDB = {
8
+ query: async (options) => {
9
+ const { host, port, user, password, query } = options;
10
+ const pool = mariadb.createPool({
11
+ host: 'host' in options ? host : '127.0.0.1',
12
+ port: 'port' in options ? port : 3306,
13
+ user: 'user' in options ? user : 'root',
14
+ password: 'password' in options ? password : '',
15
+ });
16
+ let conn, result;
17
+ try {
18
+ conn = await pool.getConnection();
19
+ result = await conn.query(query, { supportBigNumbers: true, bigNumberStrings: true });
20
+ logger.info(query, result);
21
+ } catch (error) {
22
+ if (error.stack.startsWith('TypeError: Do not know how to serialize a BigInt')) return;
23
+ logger.error(error, error.stack);
24
+ } finally {
25
+ if (conn) conn.release(); //release to pool
26
+ await pool.end();
27
+ }
28
+
29
+ return result;
30
+ },
31
+ };
32
+
33
+ export { MariaDB };
@@ -0,0 +1,46 @@
1
+ import mongoose from 'mongoose';
2
+
3
+ import { loggerFactory } from '../../server/logger.js';
4
+ import { getCapVariableName } from '../../server/conf.js';
5
+
6
+ const logger = loggerFactory(import.meta);
7
+
8
+ const MongooseDB = {
9
+ connect: async (host, name) => {
10
+ const uri = `${host}/${name}`;
11
+ // logger.info('MongooseDB connect', { host, name, uri });
12
+ return await mongoose.createConnection(uri).asPromise();
13
+ return new Promise((resolve, reject) =>
14
+ mongoose
15
+ .connect(
16
+ uri,
17
+ // ,{
18
+ // useNewUrlParser: true,
19
+ // useUnifiedTopology: true,
20
+ // }
21
+ )
22
+ .then((db) => {
23
+ logger.info(`db connected`, uri);
24
+ return resolve(db);
25
+ })
26
+ .catch((err) => {
27
+ logger.error(err, { host, name, error: err.stack });
28
+ // return reject(err);
29
+ return resolve(undefined);
30
+ }),
31
+ );
32
+ },
33
+ loadModels: async function (options = { apis: ['test'], conn: new mongoose.Connection() }) {
34
+ const { conn, apis } = options;
35
+ const models = {};
36
+ for (const api of apis) {
37
+ const { ProviderSchema } = await import(`../../api/${api}/${api}.model.js`);
38
+ const keyModel = getCapVariableName(api);
39
+ models[keyModel] = conn.model(keyModel, ProviderSchema);
40
+ }
41
+
42
+ return models;
43
+ },
44
+ };
45
+
46
+ export { MongooseDB };
package/src/dns.js ADDED
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ // https://nodejs.org/api
4
+ // https://expressjs.com/en/4x/api.html
5
+
6
+ import dotenv from 'dotenv';
7
+ import { loggerFactory } from './server/logger.js';
8
+ import { Dns } from './server/dns.js';
9
+ import { ProcessController } from './server/process.js';
10
+ import { Config } from './server/conf.js';
11
+
12
+ dotenv.config();
13
+
14
+ await Config.build();
15
+
16
+ const logger = loggerFactory(import.meta);
17
+
18
+ await logger.setUpInfo();
19
+
20
+ await Dns.InitIpDaemon();
21
+
22
+ ProcessController.init(logger);
@@ -0,0 +1,69 @@
1
+ import { srcFormatted } from '../server/client-formatted.js';
2
+ import fs from 'fs-extra';
3
+
4
+ const EmailRender = {
5
+ style: {
6
+ body: {
7
+ 'font-family': 'Arial, sans-serif',
8
+ 'background-color': '#f4f4f4',
9
+ margin: 0,
10
+ padding: '20px',
11
+ 'min-height': '300px',
12
+ width: '100%',
13
+ 'max-width': '700px',
14
+ display: 'block',
15
+ },
16
+ '.container': {
17
+ 'max-width': '600px',
18
+ margin: '0 auto',
19
+ 'background-color': '#ffffff',
20
+ padding: '20px',
21
+ 'border-radius': '5px',
22
+ // 'box-shadow': '0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)',
23
+ },
24
+ h1: {
25
+ 'font-size': '24px',
26
+ 'margin-bottom': '20px',
27
+ color: '#333333',
28
+ },
29
+ p: {
30
+ 'font-size': '16px',
31
+ 'line-height': 1.5,
32
+ 'margin-bottom': '20px',
33
+ color: '#666666',
34
+ },
35
+ button: {
36
+ display: 'inline-block',
37
+ padding: '10px 20px',
38
+ 'background-color': '#007bff',
39
+ color: '#ffffff',
40
+ 'text-decoration': 'none',
41
+ 'border-radius': '5px',
42
+ 'font-size': '16px',
43
+ },
44
+ '.footer': {
45
+ 'text-align': 'center',
46
+ padding: '20px',
47
+ 'font-size': '14px',
48
+ color: '#999999',
49
+ },
50
+ },
51
+ renderStyle: function (classObj) {
52
+ return Object.keys(this.style[classObj])
53
+ .map((classKey) => ` ${classKey}: ${this.style[classObj][classKey]};`)
54
+ .join(``);
55
+ },
56
+
57
+ getTemplates: async function (options = { templates: {} }) {
58
+ const templates = {};
59
+ for (const templateKey of Object.keys(options.templates)) {
60
+ const ssrEmailComponent = options.templates[templateKey];
61
+ let SrrComponent;
62
+ eval(await srcFormatted(fs.readFileSync(`./src/client/ssr/email-components/${ssrEmailComponent}.js`, 'utf8')));
63
+ templates[templateKey] = SrrComponent(this, options);
64
+ }
65
+ return templates;
66
+ },
67
+ };
68
+
69
+ export { EmailRender };
@@ -0,0 +1,96 @@
1
+ import nodemailer from 'nodemailer';
2
+ import { loggerFactory } from '../server/logger.js';
3
+ import { EmailRender } from './EmailRender.js';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ const MailerProvider = {
8
+ instance: {},
9
+ load: async function (
10
+ options = {
11
+ id: '',
12
+ meta: 'mailer',
13
+ sender: {
14
+ email: '',
15
+ name: '',
16
+ },
17
+ transport: {
18
+ host: '', // smtp host
19
+ port: 587,
20
+ secure: false, // true for 465, false for other ports
21
+ auth: {
22
+ user: '', // generated ethereal user
23
+ pass: '', // generated ethereal password
24
+ },
25
+ },
26
+ host: '',
27
+ path: '',
28
+ templates: ['SsrTemplate'],
29
+ },
30
+ ) {
31
+ try {
32
+ const { id } = options;
33
+ // Generate test SMTP service account from ethereal.email
34
+ // Only needed if you don't have a real mail account for testing
35
+ // let testAccount = await nodemailer.createTestAccount();
36
+
37
+ // create reusable transporter object using the default SMTP transport
38
+ const transporter = nodemailer.createTransport(options.transport);
39
+
40
+ // console.log('load logger', { url: options.meta });
41
+ this.instance[id] = {
42
+ ...options,
43
+ transporter,
44
+ templates: await EmailRender.getTemplates(options),
45
+ };
46
+
47
+ return this.instance[id];
48
+ } catch (error) {
49
+ logger.error(error, error.stack);
50
+ return undefined;
51
+ }
52
+ },
53
+ send: async function (
54
+ options = {
55
+ id: '',
56
+ sendOptions: {
57
+ from: '"Fred Foo 👻" <foo@example.com>', // sender address
58
+ to: 'bar@example.com, baz@example.com', // list of receivers
59
+ subject: 'Hello ✔', // Subject line
60
+ text: 'Hello world?', // plain text body
61
+ html: '<b>Hello world?</b>', // html body
62
+ attachments: [
63
+ {
64
+ filename: 'logo.png',
65
+ path: `./logo.png`,
66
+ cid: 'logo', // <img src='cid:logo'>
67
+ },
68
+ ],
69
+ },
70
+ },
71
+ ) {
72
+ try {
73
+ const { id, sendOptions } = options;
74
+ if (!sendOptions.from) sendOptions.from = `${this.instance[id].sender.name} <${this.instance[id].sender.email}>`;
75
+
76
+ // send mail with defined transport object
77
+ const info = await this.instance[id].transporter.sendMail(sendOptions);
78
+
79
+ // console.log('Message sent: %s', info.messageId);
80
+ // logger.info('Message sent', info);
81
+
82
+ // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>
83
+
84
+ // Preview only available when sending through an Ethereal account
85
+ // console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
86
+ // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
87
+
88
+ return info;
89
+ } catch (error) {
90
+ logger.error(error, error.stack);
91
+ return undefined;
92
+ }
93
+ },
94
+ };
95
+
96
+ export { MailerProvider };
package/src/proxy.js ADDED
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ // https://nodejs.org/api
4
+ // https://expressjs.com/en/4x/api.html
5
+
6
+ import dotenv from 'dotenv';
7
+ import { loggerFactory } from './server/logger.js';
8
+ import { buildProxy } from './server/proxy.js';
9
+ import { ProcessController } from './server/process.js';
10
+ import { Config } from './server/conf.js';
11
+
12
+ dotenv.config();
13
+
14
+ await Config.build();
15
+
16
+ const logger = loggerFactory(import.meta);
17
+
18
+ await logger.setUpInfo();
19
+
20
+ await buildProxy();
21
+
22
+ ProcessController.init(logger);
@@ -0,0 +1,44 @@
1
+ import fs from 'fs-extra';
2
+ import { network } from '../../server/network.js';
3
+ import { shellExec } from '../../server/process.js';
4
+ import { timer } from '../../client/components/core/CommonJs.js';
5
+
6
+ const Lampp = {
7
+ ports: [],
8
+ initService: async function (options = { daemon: false }) {
9
+ let cmd;
10
+ // linux
11
+ fs.writeFileSync(`/opt/lampp/apache2/conf/httpd.conf`, this.router || '', 'utf8');
12
+ cmd = `sudo /opt/lampp/lampp stop`;
13
+ shellExec(cmd);
14
+ await network.port.portClean(3306);
15
+ for (const port of this.ports) await network.port.portClean(port);
16
+ cmd = `sudo /opt/lampp/lampp start`;
17
+ if (this.router) fs.writeFileSync(`./tmp/lampp-router.conf`, this.router, 'utf-8');
18
+ shellExec(cmd, { async: true });
19
+ if (options && options.daemon) this.daemon();
20
+ },
21
+ daemon: async function () {
22
+ await timer(1000 * 60 * 2); // 2 minutes
23
+ for (const port of this.ports) {
24
+ const [portStatus] = await network.port.status([port]);
25
+ if (!portStatus.open) return await this.initService();
26
+ }
27
+ this.daemon();
28
+ },
29
+ enabled: () => fs.existsSync(`/opt/lampp/apache2/conf/httpd.conf`),
30
+ appendRouter: function (render) {
31
+ if (!this.router) {
32
+ if (fs.existsSync(`./tmp/lampp-router.conf`))
33
+ return (this.router = fs.readFileSync(`./tmp/lampp-router.conf`, 'utf-8')) + render;
34
+ return (this.router = render);
35
+ }
36
+ return (this.router += render);
37
+ },
38
+ removeRouter: function () {
39
+ this.router = undefined;
40
+ if (fs.existsSync(`./tmp/lampp-router.conf`)) fs.rmSync(`./tmp/lampp-router.conf`);
41
+ },
42
+ };
43
+
44
+ export { Lampp };
@@ -0,0 +1,3 @@
1
+ const Nginx = {};
2
+
3
+ export { Nginx };
@@ -0,0 +1,49 @@
1
+ import fs from 'fs-extra';
2
+ import { network } from '../../server/network.js';
3
+ import { shellExec } from '../../server/process.js';
4
+ import { timer } from '../../client/components/core/CommonJs.js';
5
+
6
+ const Xampp = {
7
+ ports: [],
8
+ initService: async function (options = { daemon: false }) {
9
+ let cmd;
10
+ // windows
11
+ fs.writeFileSync(
12
+ `C:/xampp/apache/conf/httpd.conf`,
13
+ fs.readFileSync(`C:/xampp/apache/conf/httpd.template.conf`, 'utf8').replace(`Listen 80`, ``),
14
+ 'utf8',
15
+ );
16
+ fs.writeFileSync(`C:/xampp/apache/conf/extra/httpd-ssl.conf`, this.router || '', 'utf8');
17
+ cmd = `C:/xampp/xampp_stop.exe`;
18
+ shellExec(cmd);
19
+ await network.port.portClean(3306);
20
+ for (const port of this.ports) await network.port.portClean(port);
21
+ cmd = `C:/xampp/xampp_start.exe`;
22
+ if (this.router) fs.writeFileSync(`./tmp/xampp-router.conf`, this.router, 'utf-8');
23
+ 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
+ },
34
+ enabled: () => fs.existsSync(`C:/xampp/apache/conf/httpd.conf`),
35
+ appendRouter: function (render) {
36
+ if (!this.router) {
37
+ if (fs.existsSync(`./tmp/xampp-router.conf`))
38
+ return (this.router = fs.readFileSync(`./tmp/xampp-router.conf`, 'utf-8')) + render;
39
+ return (this.router = render);
40
+ }
41
+ return (this.router += render);
42
+ },
43
+ removeRouter: function () {
44
+ this.router = undefined;
45
+ if (fs.existsSync(`./tmp/xampp-router.conf`)) fs.rmSync(`./tmp/xampp-router.conf`);
46
+ },
47
+ };
48
+
49
+ export { Xampp };
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Module for managing identity and authorization
3
+ * @module src/server/auth.js
4
+ * @namespace Auth
5
+ */
6
+
7
+ import dotenv from 'dotenv';
8
+ import jwt from 'jsonwebtoken';
9
+ import { loggerFactory } from './logger.js';
10
+ import crypto from 'crypto';
11
+ import { userRoleEnum } from '../api/user/user.model.js';
12
+ import { validatePassword } from '../client/components/core/CommonJs.js';
13
+
14
+ dotenv.config();
15
+
16
+ const logger = loggerFactory(import.meta);
17
+
18
+ /* The `const config` object is defining parameters related to the hashing process used for password
19
+ security. Here's a breakdown of each property in the `config` object: */
20
+ const config = {
21
+ hashBytes: 32,
22
+ saltBytes: 16,
23
+ iterations: 872791,
24
+ digest: 'sha512',
25
+ };
26
+
27
+ /**
28
+ * @param {String} password - given password to hash
29
+ * @returns {String} the hash corresponding to the password
30
+ * @memberof Auth
31
+ */
32
+ function hashPassword(password) {
33
+ const { iterations, hashBytes, digest, saltBytes } = config;
34
+ const salt = crypto.randomBytes(saltBytes).toString('hex');
35
+ const hash = crypto.pbkdf2Sync(password, salt, iterations, hashBytes, digest).toString('hex');
36
+ return [salt, hash].join('$');
37
+ }
38
+
39
+ /**
40
+ * @param {String} password - password to verify
41
+ * @param {String} combined - a combined salt + hash returned by hashPassword function
42
+ * @returns {Boolean} true if password correspond to the hash. False otherwise
43
+ * @memberof Auth
44
+ */
45
+ function verifyPassword(password, combined) {
46
+ const { iterations, hashBytes, digest } = config;
47
+ const [salt, originalHash] = combined.split('$');
48
+ const hash = crypto.pbkdf2Sync(password, salt, iterations, hashBytes, digest).toString('hex');
49
+ return hash === originalHash;
50
+ }
51
+
52
+ // jwt middleware
53
+
54
+ /**
55
+ * The hashJWT function generates a JSON Web Token (JWT) with a specified payload and expiration time.
56
+ * @param payload - The `payload` parameter in the `hashJWT` function is the data that you want to
57
+ * encode into the JSON Web Token (JWT). It typically contains information about the user or any other
58
+ * relevant data that you want to securely transmit.
59
+ * @param expire - The `expire` parameter in the `hashJWT` function is used to specify the expiration
60
+ * time for the JSON Web Token (JWT) being generated. If a value is provided for `expire`, it will be
61
+ * used as the expiration time. If `expire` is not provided (i.e., it
62
+ * @memberof Auth
63
+ */
64
+ const hashJWT = (payload, expire) =>
65
+ jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: expire !== undefined ? expire : `${process.env.EXPIRE}h` });
66
+
67
+ /**
68
+ * The function `verifyJWT` is used to verify a JSON Web Token (JWT) using a secret key stored in the
69
+ * environment variables.
70
+ * @param [token] - The `token` parameter is a JSON Web Token (JWT) that is passed to the `verifyJWT`
71
+ * function for verification.
72
+ * @memberof Auth
73
+ */
74
+ const verifyJWT = (token = '') => jwt.verify(token, process.env.JWT_SECRET);
75
+
76
+ /**
77
+ * The authMiddleware function checks and verifies the authorization token in the request headers
78
+ * before allowing access to protected routes.
79
+ * @param req - The `req` parameter in the `authMiddleware` function stands for the request object. It
80
+ * contains information about the HTTP request made to the server, including headers, body, parameters,
81
+ * and more. In this context, the function is extracting the authorization token from the request
82
+ * headers to authenticate the user.
83
+ * @param res - The `res` parameter in the `authMiddleware` function is the response object that
84
+ * represents the HTTP response that an Express.js server sends when it receives an HTTP request. It is
85
+ * used to send a response back to the client with status codes, headers, and data.
86
+ * @param next - The `next` parameter in the `authMiddleware` function is a callback function that is
87
+ * used to pass control to the next middleware function in the stack. When called, it invokes the next
88
+ * middleware function in the chain. This is a common pattern in Express.js middleware functions to
89
+ * move to the next middleware
90
+ * @returns {Object} The `req.auth` included JWT payload in request authorization
91
+ * @memberof Auth
92
+ */
93
+ const authMiddleware = (req, res, next) => {
94
+ try {
95
+ const authHeader = String(req.headers['authorization'] || req.headers['Authorization'] || '');
96
+ if (authHeader.startsWith('Bearer ')) {
97
+ const token = authHeader.substring(7, authHeader.length);
98
+ const payload = verifyJWT(token);
99
+ req.auth = payload;
100
+ return next();
101
+ }
102
+ return res.status(401).json({
103
+ status: 'error',
104
+ message: 'unauthorized: invalid token',
105
+ });
106
+ } catch (error) {
107
+ logger.error(error, error.stack);
108
+ return res.status(400).json({
109
+ status: 'error',
110
+ message: error.message,
111
+ });
112
+ }
113
+ };
114
+
115
+ /**
116
+ * The `adminGuard` function checks if the user has admin role permission and returns an error message
117
+ * if not.
118
+ * @param req - The `req` parameter typically represents the HTTP request object in Node.js. It
119
+ * contains information about the incoming request such as the request headers, parameters, body, and
120
+ * more. In the context of your `adminGuard` function, `req` is the request object that is being passed
121
+ * to the middleware
122
+ * @param res - The `res` parameter in the `adminGuard` function is the response object in Express.js.
123
+ * It is used to send a response back to the client making the HTTP request.
124
+ * @param next - The `next` parameter in the `adminGuard` function is a callback function that is used
125
+ * to pass control to the next middleware function in the stack. When called, it executes the next
126
+ * middleware function. If there are no more middleware functions in the stack, it will proceed to the
127
+ * route handler.
128
+ * @returns The `adminGuard` function is returning either a 403 status with an error message if the
129
+ * user role is not 'admin', or it is calling the `next()` function to proceed to the next middleware
130
+ * if the user role is 'admin'. If an error occurs during the process, it will log the error and return
131
+ * a 400 status with the error message.
132
+ * @memberof Auth
133
+ */
134
+ const adminGuard = (req, res, next) => {
135
+ try {
136
+ if (!(userRoleEnum.indexOf(req.auth.user.role) === userRoleEnum.indexOf('admin')))
137
+ return res.status(403).json({ status: 'error', message: 'Insufficient permission' });
138
+ return next();
139
+ } catch (error) {
140
+ logger.error(error, error.stack);
141
+ return res.status(400).json({
142
+ status: 'error',
143
+ message: error.message,
144
+ });
145
+ }
146
+ };
147
+
148
+ /**
149
+ * The function `moderatorGuard` checks if the user's role is at least a moderator and handles errors
150
+ * accordingly.
151
+ * @param req - The `req` parameter in the `moderatorGuard` function typically represents the HTTP
152
+ * request object, which contains information about the incoming request such as headers, parameters,
153
+ * body, etc. It is commonly used to access data sent from the client to the server.
154
+ * @param res - The `res` parameter in the `moderatorGuard` function is the response object in
155
+ * Express.js. It is used to send a response back to the client making the HTTP request.
156
+ * @param next - The `next` parameter in the `moderatorGuard` function is a callback function that is
157
+ * used to pass control to the next middleware function in the stack. When called, it will execute the
158
+ * next middleware function. In the context of Express.js middleware, `next` is typically called to
159
+ * move to
160
+ * @returns In the `moderatorGuard` function, if the user's role is not a moderator or higher, a 403
161
+ * status with an error message "Insufficient permission" is returned. If there is an error during the
162
+ * process, a 400 status with the error message is returned. If everything is successful, the `next()`
163
+ * function is called to proceed to the next middleware in the chain.
164
+ * @memberof Auth
165
+ */
166
+ const moderatorGuard = (req, res, next) => {
167
+ try {
168
+ if (!(userRoleEnum.indexOf(req.auth.user.role) <= userRoleEnum.indexOf('moderator')))
169
+ return res.status(403).json({ status: 'error', message: 'Insufficient permission' });
170
+ return next();
171
+ } catch (error) {
172
+ logger.error(error, error.stack);
173
+ return res.status(400).json({
174
+ status: 'error',
175
+ message: error.message,
176
+ });
177
+ }
178
+ };
179
+
180
+ const validatePasswordMiddleware = (req, password) => {
181
+ let errors = [];
182
+ if (req.body && 'password' in req.body) errors = validatePassword(req.body.password);
183
+ if (errors.length > 0)
184
+ return {
185
+ status: 'error',
186
+ message:
187
+ 'Password, ' + errors.map((e, i) => (i > 0 ? ', ' : '') + (e[req.lang] ? e[req.lang] : e['en'])).join(''),
188
+ };
189
+ else
190
+ return {
191
+ status: 'success',
192
+ };
193
+ };
194
+
195
+ export {
196
+ authMiddleware,
197
+ hashPassword,
198
+ verifyPassword,
199
+ hashJWT,
200
+ adminGuard,
201
+ moderatorGuard,
202
+ verifyJWT,
203
+ validatePasswordMiddleware,
204
+ };