@reldens/cms 0.5.0 → 0.7.0

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 (55) hide show
  1. package/README.md +1 -1
  2. package/admin/assets/admin/filters.png +0 -0
  3. package/admin/assets/admin/list.png +0 -0
  4. package/admin/reldens-admin-client.css +830 -0
  5. package/admin/reldens-admin-client.js +272 -0
  6. package/admin/templates/dashboard.html +1 -0
  7. package/admin/templates/default-copyright.html +5 -0
  8. package/admin/templates/edit.html +25 -0
  9. package/admin/templates/fields/edit/button.html +3 -0
  10. package/admin/templates/fields/edit/checkbox.html +1 -0
  11. package/admin/templates/fields/edit/file.html +2 -0
  12. package/admin/templates/fields/edit/radio.html +1 -0
  13. package/admin/templates/fields/edit/select.html +5 -0
  14. package/admin/templates/fields/edit/text.html +1 -0
  15. package/admin/templates/fields/edit/textarea.html +1 -0
  16. package/admin/templates/fields/view/boolean.html +1 -0
  17. package/admin/templates/fields/view/image.html +4 -0
  18. package/admin/templates/fields/view/images.html +7 -0
  19. package/admin/templates/fields/view/link.html +1 -0
  20. package/admin/templates/fields/view/links.html +6 -0
  21. package/admin/templates/fields/view/text.html +1 -0
  22. package/admin/templates/layout.html +37 -0
  23. package/admin/templates/list-content.html +70 -0
  24. package/admin/templates/list.html +35 -0
  25. package/admin/templates/login.html +19 -0
  26. package/admin/templates/management.html +22 -0
  27. package/admin/templates/pagination-link.html +1 -0
  28. package/admin/templates/sidebar-header.html +4 -0
  29. package/admin/templates/sidebar-item.html +3 -0
  30. package/admin/templates/sidebar.html +11 -0
  31. package/admin/templates/view.html +23 -0
  32. package/bin/reldens-cms.js +20 -8
  33. package/index.js +2 -2
  34. package/install/index.html +0 -7
  35. package/install/success.html +30 -0
  36. package/lib/admin-manager.js +1 -1
  37. package/lib/admin-templates-loader.js +37 -0
  38. package/lib/admin-translations.js +4 -218
  39. package/lib/allowed-extensions.js +11 -0
  40. package/lib/entities-loader.js +42 -0
  41. package/lib/{storefront.js → frontend.js} +14 -19
  42. package/lib/installer.js +137 -52
  43. package/lib/loaded-entities-processor.js +30 -0
  44. package/lib/manager.js +135 -37
  45. package/lib/mime-types.js +35 -0
  46. package/lib/templates-list.js +0 -9
  47. package/lib/templates-to-path-mapper.js +28 -0
  48. package/migrations/default-user.sql +2 -1
  49. package/package.json +2 -2
  50. package/templates/.env.dist +11 -11
  51. package/templates/assets/web/loading.gif +0 -0
  52. package/templates/assets/web/reldens-your-logo-mage.png +0 -0
  53. package/templates/css/styles.css +1 -1
  54. package/templates/index.js.dist +32 -0
  55. package/templates/js/scripts.js +1 -1
package/lib/installer.js CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  const { FileHandler, Encryptor } = require('@reldens/server-utils');
8
8
  const { DriversMap, EntitiesGenerator, PrismaSchemaGenerator } = require('@reldens/storage');
9
+ const { EntitiesLoader } = require('./entities-loader');
10
+ const { AdminEntitiesGenerator } = require('./admin-entities-generator');
9
11
  const { Logger, sc } = require('@reldens/utils');
10
12
  const mustache = require('mustache');
11
13
 
@@ -15,15 +17,26 @@ class Installer
15
17
  constructor(props)
16
18
  {
17
19
  this.app = sc.get(props, 'app', false);
20
+ this.appServer = sc.get(props, 'appServer', false);
18
21
  this.appServerFactory = sc.get(props, 'appServerFactory', false);
19
22
  this.projectRoot = sc.get(props, 'projectRoot', './');
20
- this.encoding = sc.get(props, 'encoding', 'utf8');
23
+ this.projectTemplatesPath = FileHandler.joinPaths(this.projectRoot, 'templates');
24
+ this.projectPublicPath = FileHandler.joinPaths(this.projectRoot, 'public');
25
+ this.projectPublicAssetsPath = FileHandler.joinPaths(this.projectPublicPath, 'assets');
26
+ this.projectCssPath = FileHandler.joinPaths(this.projectPublicPath, 'css');
27
+ this.projectJsPath = FileHandler.joinPaths(this.projectPublicPath, 'js');
21
28
  this.installLockPath = FileHandler.joinPaths(this.projectRoot, 'install.lock');
22
29
  this.envFilePath = FileHandler.joinPaths(this.projectRoot, '.env');
23
30
  this.modulePath = FileHandler.joinPaths(__dirname, '..');
24
31
  this.installerPath = FileHandler.joinPaths(this.modulePath, 'install');
25
32
  this.migrationsPath = FileHandler.joinPaths(this.modulePath, 'migrations');
26
33
  this.defaultTemplatesPath = FileHandler.joinPaths(this.modulePath, 'templates');
34
+ this.moduleAdminPath = FileHandler.joinPaths(this.modulePath, 'admin');
35
+ this.moduleAdminAssetsPath = FileHandler.joinPaths(this.moduleAdminPath, 'assets');
36
+ this.moduleAdminTemplatesPath = FileHandler.joinPaths(this.moduleAdminPath, 'templates')
37
+ this.indexTemplatePath = FileHandler.joinPaths(this.defaultTemplatesPath, 'index.js.dist');
38
+ this.postInstallCallback = sc.get(props, 'postInstallCallback', false);
39
+ this.entitiesLoader = new EntitiesLoader({projectRoot: this.projectRoot});
27
40
  }
28
41
 
29
42
  isInstalled()
@@ -31,7 +44,7 @@ class Installer
31
44
  return FileHandler.exists(this.installLockPath);
32
45
  }
33
46
 
34
- async prepareSetup(app, appServerFactory)
47
+ async prepareSetup(app, appServer, appServerFactory)
35
48
  {
36
49
  if(!app){
37
50
  Logger.error('Missing app on prepareSetup for Installer.');
@@ -43,6 +56,7 @@ class Installer
43
56
  }
44
57
  this.app = app;
45
58
  this.appServerFactory = appServerFactory;
59
+ this.appServer = appServer;
46
60
  app.use('/install-assets', appServerFactory.applicationFramework.static(this.installerPath, {index: false}));
47
61
  app.use(appServerFactory.session({
48
62
  secret: Encryptor.generateSecretKey(),
@@ -63,18 +77,44 @@ class Installer
63
77
  if(this.isInstalled()){
64
78
  return next();
65
79
  }
66
- if('' === req._parsedUrl.pathname || '/' === req._parsedUrl.pathname){
80
+ let urlPath = req._parsedUrl.pathname;
81
+ if('' === urlPath || '/' === urlPath){
67
82
  let installerIndexPath = FileHandler.joinPaths(this.installerPath, 'index.html');
68
83
  if(!FileHandler.exists(installerIndexPath)){
69
84
  return res.status(500).send('Installer template not found.');
70
85
  }
71
86
  let content = FileHandler.readFile(installerIndexPath);
72
87
  let contentParams = req.session?.templateVariables || this.fetchDefaults();
88
+ let errorParam = req.query?.error;
89
+ if(errorParam){
90
+ contentParams.errorMessage = this.getErrorMessage(errorParam);
91
+ }
73
92
  return res.send(mustache.render(content, contentParams));
74
93
  }
94
+ if('/install' !== urlPath){
95
+ return res.redirect('/');
96
+ }
75
97
  next();
76
98
  }
77
99
 
100
+ getErrorMessage(errorCode)
101
+ {
102
+ let errorMessages = {
103
+ 'invalid-driver': 'Invalid storage driver selected.',
104
+ 'connection-failed': 'Database connection failed. Please check your credentials.',
105
+ 'raw-query-not-found': 'Query method not found in driver.',
106
+ 'sql-file-not-found': 'SQL installation file not found.',
107
+ 'sql-tables-creation-failed': 'Failed to create database tables.',
108
+ 'sql-default-user-error': 'Failed to create default user.',
109
+ 'installation-entities-generation-failed': 'Failed to generate entities.',
110
+ 'installation-process-failed': 'Installation process failed.',
111
+ 'installation-entities-callback-failed': 'Failed to process entities for callback.',
112
+ 'configuration-error': 'Configuration error while completing installation.',
113
+ 'already-installed': 'The application is already installed.'
114
+ };
115
+ return errorMessages[errorCode] || 'An unknown error occurred during installation.';
116
+ }
117
+
78
118
  async executeInstallProcess(req, res)
79
119
  {
80
120
  if(this.isInstalled()){
@@ -101,7 +141,11 @@ class Installer
101
141
  debug: false
102
142
  };
103
143
  if('prisma' === selectedDriver){
104
- await this.generatePrismaSchema(dbConfig);
144
+ let generatedPrismaSchema = await this.generatePrismaSchema(dbConfig);
145
+ if(!generatedPrismaSchema){
146
+ Logger.error('Could not generated Prisma schema.');
147
+ return res.redirect('/?error=prisma-schema-generation-error');
148
+ }
105
149
  Logger.info('Generated Prisma schema.');
106
150
  }
107
151
  let dbDriver = new driverClass(dbConfig);
@@ -129,7 +173,7 @@ class Installer
129
173
  if(FileHandler.exists(defaultUserSqlPath)){
130
174
  let queryUserResult = await this.executeQueryFile(dbDriver, defaultUserSqlPath);
131
175
  if(!queryUserResult){
132
- Logger.error('Default user creation failed.');
176
+ Logger.error('Default user creation failed.', queryUserResult);
133
177
  return res.redirect('/?error=sql-default-user-error');
134
178
  }
135
179
  Logger.info('Created default user.');
@@ -144,19 +188,29 @@ class Installer
144
188
  Logger.error('Installation error: '+error.message);
145
189
  return res.redirect('/?error=installation-process-failed');
146
190
  }
147
- if('' === templateVariables['app-admin-path']){
148
- templateVariables['app-admin-path'] = '/reldens-admin';
149
- }
150
191
  try {
151
192
  await this.createEnvFile(templateVariables);
152
- await this.createLockFile();
153
193
  await this.prepareProjectDirectories();
194
+ await this.copyAdminDirectory();
195
+ await this.createIndexJsFile(templateVariables);
196
+ if(sc.isFunction(this.postInstallCallback)){
197
+ if(this.appServer && sc.isFunction(this.appServer.close)){
198
+ await this.appServer.close();
199
+ }
200
+ Logger.debug('Running postInstallCallback.');
201
+ await this.postInstallCallback(this.entitiesLoader.loadEntities(selectedDriver));
202
+ }
203
+ await this.createLockFile();
154
204
  Logger.info('Installation successful!');
155
- let adminPath = templateVariables['app-admin-path'];
156
- return res.redirect(adminPath);
205
+ let successContent = 'Installation successful! Run "node ." to start your CMS.';
206
+ let successFileContent = FileHandler.readFile(FileHandler.joinPaths(this.installerPath, 'success.html'));
207
+ if(successFileContent){
208
+ successContent = mustache.render(successFileContent, {adminPath: templateVariables['app-admin-path']});
209
+ }
210
+ return res.send(successContent);
157
211
  } catch (error) {
158
- Logger.error('Configuration error: '+error.message);
159
- return res.redirect('/?error=configuration-error');
212
+ Logger.critical('Configuration error: '+error.message);
213
+ return res.redirect('/?error=installation-error');
160
214
  }
161
215
  }
162
216
 
@@ -213,56 +267,87 @@ class Installer
213
267
  dbDriver: templateVariables['db-storage-driver'],
214
268
  adminPath: templateVariables['app-admin-path'],
215
269
  adminSecret: Encryptor.generateSecretKey(),
216
- host: templateVariables['app-host'] || 'http://localhost',
217
- port: templateVariables['app-port'] || '8000'
270
+ host: templateVariables['app-host'],
271
+ port: templateVariables['app-port']
218
272
  });
219
273
  return FileHandler.writeFile(this.envFilePath, envContent);
220
274
  }
221
275
 
276
+ async createIndexJsFile(templateVariables)
277
+ {
278
+ if(!FileHandler.exists(this.indexTemplatePath)){
279
+ Logger.error('Index.js template not found: '+this.indexTemplatePath);
280
+ return false;
281
+ }
282
+ let indexTemplate = FileHandler.readFile(this.indexTemplatePath);
283
+ let driverKey = templateVariables['db-storage-driver'];
284
+ let indexContent = mustache.render(indexTemplate, {driverKey});
285
+ let indexFilePath = FileHandler.joinPaths(this.projectRoot, 'index.js');
286
+ if(FileHandler.exists(indexFilePath)){
287
+ Logger.info('Index.js file already exists, the CMS installer will not override the existent one.');
288
+ return true;
289
+ }
290
+ return FileHandler.writeFile(indexFilePath, indexContent);
291
+ }
292
+
222
293
  async createLockFile()
223
294
  {
224
- return FileHandler.writeFile(this.installLockPath,
225
- 'Installation completed on '+new Date().toISOString());
295
+ return FileHandler.writeFile(this.installLockPath, 'Installation completed on '+new Date().toISOString());
226
296
  }
227
297
 
228
- async prepareProjectDirectories()
298
+ async copyAdminDirectory()
229
299
  {
230
- let projectTemplatesPath = FileHandler.joinPaths(this.projectRoot, 'templates');
231
- if(!FileHandler.exists(projectTemplatesPath)){
232
- FileHandler.createFolder(projectTemplatesPath);
233
- }
234
- let projectPublicPath = FileHandler.joinPaths(this.projectRoot, 'public');
235
- if(!FileHandler.exists(projectPublicPath)){
236
- FileHandler.createFolder(projectPublicPath);
237
- }
238
- let projectCssPath = FileHandler.joinPaths(projectPublicPath, 'css');
239
- if(!FileHandler.exists(projectCssPath)){
240
- FileHandler.createFolder(projectCssPath);
241
- }
242
- let projectJsPath = FileHandler.joinPaths(projectPublicPath, 'js');
243
- if(!FileHandler.exists(projectJsPath)){
244
- FileHandler.createFolder(projectJsPath);
245
- }
246
- let defaultPagePath = FileHandler.joinPaths(this.defaultTemplatesPath, 'page.html');
247
- let defaultNotFoundPath = FileHandler.joinPaths(this.defaultTemplatesPath, '404.html');
248
- let defaultLayoutPath = FileHandler.joinPaths(this.defaultTemplatesPath, 'layout.html');
249
- if(FileHandler.exists(defaultPagePath)){
250
- FileHandler.copyFile(defaultPagePath, FileHandler.joinPaths(projectTemplatesPath, 'page.html'));
251
- }
252
- if(FileHandler.exists(defaultNotFoundPath)){
253
- FileHandler.copyFile(defaultNotFoundPath, FileHandler.joinPaths(projectTemplatesPath, '404.html'));
300
+ let projectAdminPath = FileHandler.joinPaths(this.projectRoot, 'admin');
301
+ if(FileHandler.exists(projectAdminPath)){
302
+ Logger.info('Admin folder already exists in project root.');
303
+ return true;
254
304
  }
255
- if(FileHandler.exists(defaultLayoutPath)){
256
- FileHandler.copyFile(defaultLayoutPath, FileHandler.joinPaths(projectTemplatesPath, 'layout.html'));
257
- }
258
- let defaultCssPath = FileHandler.joinPaths(this.defaultTemplatesPath, 'css', 'styles.css');
259
- let defaultJsPath = FileHandler.joinPaths(this.defaultTemplatesPath, 'js', 'scripts.js');
260
- if(FileHandler.exists(defaultCssPath)){
261
- FileHandler.copyFile(defaultCssPath, FileHandler.joinPaths(projectCssPath, 'styles.css'));
262
- }
263
- if(FileHandler.exists(defaultJsPath)){
264
- FileHandler.copyFile(defaultJsPath, FileHandler.joinPaths(projectJsPath, 'scripts.js'));
305
+ if(!FileHandler.exists(this.moduleAdminPath)){
306
+ Logger.error('Admin folder not found in module path: '+this.moduleAdminPath);
307
+ return false;
265
308
  }
309
+ let projectAdminTemplates = FileHandler.joinPaths(projectAdminPath, 'templates');
310
+ FileHandler.copyFolderSync(this.moduleAdminTemplatesPath, projectAdminTemplates);
311
+ FileHandler.copyFolderSync(this.moduleAdminAssetsPath, this.projectPublicAssetsPath);
312
+ FileHandler.copyFile(
313
+ FileHandler.joinPaths(this.moduleAdminPath, 'reldens-admin-client.css'),
314
+ FileHandler.joinPaths(this.projectCssPath, 'reldens-admin-client.css'),
315
+ );
316
+ FileHandler.copyFile(
317
+ FileHandler.joinPaths(this.moduleAdminPath, 'reldens-admin-client.js'),
318
+ FileHandler.joinPaths(this.projectJsPath, 'reldens-admin-client.js'),
319
+ );
320
+ Logger.info('Admin folder copied to project root.');
321
+ return true;
322
+ }
323
+
324
+ async prepareProjectDirectories()
325
+ {
326
+ FileHandler.createFolder(this.projectTemplatesPath);
327
+ FileHandler.createFolder(this.projectPublicPath);
328
+ FileHandler.createFolder(this.projectPublicAssetsPath);
329
+ FileHandler.createFolder(this.projectCssPath);
330
+ FileHandler.createFolder(this.projectJsPath);
331
+ FileHandler.copyFile(
332
+ FileHandler.joinPaths(this.defaultTemplatesPath, 'page.html'),
333
+ FileHandler.joinPaths(this.projectTemplatesPath, 'page.html')
334
+ );
335
+ FileHandler.copyFile(
336
+ FileHandler.joinPaths(this.defaultTemplatesPath, '404.html'),
337
+ FileHandler.joinPaths(this.projectTemplatesPath, '404.html')
338
+ );
339
+ FileHandler.copyFile(
340
+ FileHandler.joinPaths(this.defaultTemplatesPath, 'layout.html'),
341
+ FileHandler.joinPaths(this.projectTemplatesPath, 'layout.html')
342
+ );
343
+ FileHandler.copyFile(
344
+ FileHandler.joinPaths(this.defaultTemplatesPath, 'css', 'styles.css'),
345
+ FileHandler.joinPaths(this.projectCssPath, 'styles.css')
346
+ );
347
+ FileHandler.copyFile(
348
+ FileHandler.joinPaths(this.defaultTemplatesPath, 'js', 'scripts.js'),
349
+ FileHandler.joinPaths(this.projectJsPath, 'scripts.js')
350
+ );
266
351
  return true;
267
352
  }
268
353
 
@@ -0,0 +1,30 @@
1
+ /**
2
+ *
3
+ * Reldens - LoadedEntitiesProcessor
4
+ *
5
+ */
6
+
7
+ const { sc } = require('@reldens/utils');
8
+
9
+ class LoadedEntitiesProcessor
10
+ {
11
+
12
+ process(rawRegisteredEntities, entitiesTranslations, entitiesConfig)
13
+ {
14
+ let exportedEntitiesList = Object.keys(rawRegisteredEntities);
15
+ if(0 === exportedEntitiesList.length){
16
+ return {};
17
+ }
18
+ let entities = {};
19
+ for (let i of exportedEntitiesList) {
20
+ entities[i] = {
21
+ rawEntity: rawRegisteredEntities[i],
22
+ config: sc.isFunction(entitiesConfig) ? entitiesConfig(props)[i] : entitiesConfig[i]
23
+ };
24
+ }
25
+ return {entities, entitiesRaw: rawRegisteredEntities, translations: entitiesTranslations};
26
+ }
27
+
28
+ }
29
+
30
+ module.exports.LoadedEntitiesProcessor = new LoadedEntitiesProcessor();
package/lib/manager.js CHANGED
@@ -4,17 +4,27 @@
4
4
  *
5
5
  */
6
6
 
7
- const { AppServerFactory, FileHandler, Encryptor } = require('@reldens/server-utils');
8
- const { DriversMap } = require('@reldens/storage');
7
+ const { TemplatesList } = require('./templates-list');
8
+ const { AdminTranslations } = require('./admin-translations');
9
+ const { AdminTemplatesLoader } = require('./admin-templates-loader');
10
+ const { AdminManagerValidator } = require('./admin-manager-validator');
11
+ const { MimeTypes } = require('./mime-types');
12
+ const { AllowedExtensions } = require('./allowed-extensions');
13
+ const { TemplatesToPathMapper } = require('./templates-to-path-mapper');
14
+ const { AdminEntitiesGenerator } = require('./admin-entities-generator');
15
+ const { LoadedEntitiesProcessor } = require('./loaded-entities-processor');
9
16
  const { AdminManager } = require('./admin-manager');
10
17
  const { Installer } = require('./installer');
11
- const { Storefront } = require('./storefront');
12
- const { Logger, sc } = require('@reldens/utils');
18
+ const { Frontend } = require('./frontend');
19
+ const { EventsManagerSingleton, Logger, sc } = require('@reldens/utils');
20
+ const { DriversMap } = require('@reldens/storage');
21
+ const { AppServerFactory, FileHandler, Encryptor } = require('@reldens/server-utils');
13
22
  const dotenv = require('dotenv');
14
23
  const mustache = require('mustache');
15
24
 
16
25
  class Manager
17
26
  {
27
+
18
28
  constructor(props = {})
19
29
  {
20
30
  this.projectRoot = sc.get(props, 'projectRoot', './');
@@ -22,35 +32,54 @@ class Manager
22
32
  this.installLockPath = FileHandler.joinPaths(this.projectRoot, 'install.lock');
23
33
  dotenv.config({path: this.envFilePath});
24
34
  this.config = this.loadConfigFromEnv();
25
- this.entities = sc.get(props, 'entities', {});
35
+ this.adminEntities = sc.get(props, 'adminEntities', {});
36
+ this.rawRegisteredEntities = sc.get(props, 'rawRegisteredEntities', {});
37
+ this.entitiesTranslations = sc.get(props, 'entitiesTranslations', {});
38
+ this.entitiesConfig = sc.get(props, 'entitiesConfig', {});
39
+ this.processedEntities = sc.get(props, 'processedEntities', {});
26
40
  this.authenticationMethod = sc.get(props, 'authenticationMethod', 'db-users');
27
41
  this.authenticationCallback = sc.get(props, 'authenticationCallback', false);
42
+ this.events = sc.get(props, 'events', EventsManagerSingleton);
43
+ this.adminTemplatesList = sc.get(props, 'adminTemplatesList', TemplatesList);
44
+ this.projectAdminPath = FileHandler.joinPaths(this.projectRoot, 'admin');
45
+ this.projectAdminTemplatesPath = FileHandler.joinPaths(this.projectAdminPath, 'templates');
46
+ this.mimeTypes = sc.get(props, 'mimeTypes', MimeTypes);
47
+ this.allowedExtensions = sc.get(props, 'allowedExtensions', AllowedExtensions)
48
+ this.adminRoleId = sc.get(props, 'adminRoleId', 99);
49
+ this.stylesFilePath = sc.get(props, 'stylesFilePath', '/css/reldens-admin-client.css');
50
+ this.scriptsFilePath = sc.get(props, 'scriptsFilePath', '/js/reldens-admin-client.js');
51
+ this.companyName = sc.get(props, 'companyName', 'Reldens - CMS');
52
+ this.logo = sc.get(props, 'logo', '/assets/web/reldens-your-logo-mage.png');
53
+ this.favicon = sc.get(props, 'favicon', '/assets/web/favicon.ico');
28
54
  this.appServerFactory = new AppServerFactory();
55
+ this.adminEntitiesGenerator = new AdminEntitiesGenerator();
29
56
  this.installer = new Installer({
30
- projectRoot: this.projectRoot
57
+ projectRoot: this.projectRoot,
58
+ postInstallCallback: this.initializeCmsAfterInstall.bind(this)
31
59
  });
32
60
  this.dataServer = false;
33
61
  this.app = false;
34
62
  this.appServer = false;
35
63
  this.adminManager = false;
36
- this.storefront = false;
64
+ this.frontend = false;
37
65
  }
38
66
 
39
67
  loadConfigFromEnv()
40
68
  {
69
+ let envVars = process.env;
41
70
  return {
42
- host: process.env.RELDENS_CMS_HOST || 'http://localhost',
43
- port: Number(process.env.RELDENS_CMS_PORT || 8000),
44
- adminPath: process.env.RELDENS_CMS_ADMIN_PATH || '/reldens-admin',
45
- adminSecret: process.env.RELDENS_CMS_ADMIN_SECRET || '',
71
+ host: sc.get(envVars, 'RELDENS_CMS_HOST', 'http://localhost'),
72
+ port: Number(sc.get(envVars, 'RELDENS_CMS_PORT', 8000)),
73
+ adminPath: sc.get(envVars, 'RELDENS_CMS_ADMIN_PATH', '/reldens-admin'),
74
+ adminSecret: sc.get(envVars, 'RELDENS_CMS_ADMIN_SECRET', ''),
46
75
  database: {
47
- client: process.env.RELDENS_CMS_DB_CLIENT || 'mysql',
48
- host: process.env.RELDENS_CMS_DB_HOST || 'localhost',
49
- port: Number(process.env.RELDENS_CMS_DB_PORT || 3306),
50
- name: process.env.RELDENS_CMS_DB_NAME || 'reldens_cms',
51
- user: process.env.RELDENS_CMS_DB_USER || '',
52
- password: process.env.RELDENS_CMS_DB_PASSWORD || '',
53
- driver: process.env.RELDENS_CMS_DB_DRIVER || 'prisma'
76
+ client: sc.get(envVars, 'RELDENS_CMS_DB_CLIENT', 'mysql'),
77
+ host: sc.get(envVars, 'RELDENS_CMS_DB_HOST', 'localhost'),
78
+ port: Number(sc.get(envVars, 'RELDENS_CMS_DB_PORT', 3306)),
79
+ name: sc.get(envVars, 'RELDENS_CMS_DB_NAME', 'reldens_cms'),
80
+ user: sc.get(envVars, 'RELDENS_CMS_DB_USER', ''),
81
+ password: sc.get(envVars, 'RELDENS_CMS_DB_PASSWORD', ''),
82
+ driver: sc.get(envVars, 'RELDENS_CMS_DB_DRIVER', 'prisma')
54
83
  }
55
84
  };
56
85
  }
@@ -71,24 +100,64 @@ class Manager
71
100
  this.appServer = createdAppServer.appServer;
72
101
  if(!this.isInstalled()){
73
102
  Logger.info('CMS not installed, preparing setup');
74
- await this.installer.prepareSetup(this.app, this.appServerFactory);
103
+ await this.installer.prepareSetup(this.app, this.appServer, this.appServerFactory);
75
104
  await this.appServer.listen(this.config.port);
76
105
  Logger.info('Installer running on '+this.config.host+':'+this.config.port);
77
106
  return true;
78
107
  }
79
108
  try {
80
- await this.initializeDataServer();
81
- await this.initializeAdminManager();
82
- await this.initializeStorefront();
83
- await this.appServer.listen(this.config.port);
109
+ await this.initializeServices();
84
110
  Logger.info('CMS running on '+this.config.host+':'+this.config.port);
85
111
  return true;
86
112
  } catch (error) {
87
- Logger.error('Failed to start CMS: '+error.message);
113
+ Logger.critical('Failed to start CMS: '+error.message);
114
+ return false;
115
+ }
116
+ }
117
+
118
+ async initializeCmsAfterInstall(loadEntities)
119
+ {
120
+ try {
121
+ this.rawRegisteredEntities = loadEntities.rawRegisteredEntities;
122
+ this.entitiesTranslations = loadEntities.entitiesTranslations;
123
+ this.entitiesConfig = loadEntities.entitiesConfig;
124
+ this.dataServer.rawEntities = loadEntities.rawRegisteredEntities;
125
+ this.config = this.loadConfigFromEnv();
126
+ await this.initializeServices();
127
+ Logger.info('CMS initialized after installation on '+this.config.host+':'+this.config.port);
128
+ return true;
129
+ } catch (error) {
130
+ Logger.critical('Failed to initialize CMS after installation: '+error.message);
88
131
  return false;
89
132
  }
90
133
  }
91
134
 
135
+ async initializeServices()
136
+ {
137
+ await this.initializeDataServer();
138
+ if (0 === Object.keys(this.adminEntities).length){
139
+ if(0 === Object.keys(this.processedEntities).length){
140
+ this.processedEntities = LoadedEntitiesProcessor.process(
141
+ this.rawRegisteredEntities,
142
+ this.entitiesTranslations,
143
+ this.entitiesConfig
144
+ );
145
+ }
146
+ if(!this.processedEntities.entities){
147
+ Logger.critical('Processed entities undefined.');
148
+ return false;
149
+ }
150
+ await this.dataServer.generateEntities();
151
+ this.adminEntities = this.adminEntitiesGenerator.generate(
152
+ this.processedEntities.entities,
153
+ this.dataServer.entityManager.entities
154
+ );
155
+ }
156
+ await this.initializeAdminManager();
157
+ await this.initializeFrontend();
158
+ await this.appServer.listen(this.config.port);
159
+ }
160
+
92
161
  async initializeDataServer()
93
162
  {
94
163
  let dbConfig = {
@@ -99,15 +168,18 @@ class Manager
99
168
  database: this.config.database.name,
100
169
  user: this.config.database.user,
101
170
  password: this.config.database.password
102
- }
171
+ },
172
+ rawEntities: this.rawRegisteredEntities
103
173
  };
104
174
  let DriverClass = DriversMap[this.config.database.driver];
105
175
  if(!DriverClass){
106
- throw new Error('Invalid database driver: '+this.config.database.driver);
176
+ Logger.critical('Invalid database driver: '+this.config.database.driver);
177
+ return false;
107
178
  }
108
179
  this.dataServer = new DriverClass(dbConfig);
109
180
  if(!await this.dataServer.connect()){
110
- throw new Error('Failed to connect to database');
181
+ Logger.critical('Failed to connect to database.');
182
+ return false;
111
183
  }
112
184
  await this.dataServer.generateEntities();
113
185
  return true;
@@ -116,33 +188,58 @@ class Manager
116
188
  async initializeAdminManager()
117
189
  {
118
190
  let authenticationCallback = this.authenticationCallback;
119
- if('db-users' === this.authenticationMethod){
191
+ if('db-users' === this.authenticationMethod && !authenticationCallback){
120
192
  authenticationCallback = async (email, password, roleId) => {
193
+ Logger.debug('Running default "db-users" authentication.');
121
194
  let usersEntity = this.dataServer.getEntity('users');
122
195
  if(!usersEntity){
196
+ Logger.critical('No users entity found.');
123
197
  return false;
124
198
  }
125
199
  let user = await usersEntity.loadOneBy('email', email);
126
200
  if(!user){
201
+ Logger.debug('User not found by email: '+email+'.', user);
127
202
  return false;
128
203
  }
129
204
  if(Number(user.role_id) !== Number(roleId)){
205
+ Logger.debug('Invalid user role ID: '+roleId+' / '+user.role_id+'.');
130
206
  return false;
131
207
  }
132
- return Encryptor.validatePassword(password, user.password) ? user : false;
208
+ let passwordResult = Encryptor.validatePassword(password, user.password) ? user : false;
209
+ if(!passwordResult){
210
+ Logger.debug('Invalid user password for: '+email+'.');
211
+ }
212
+ return passwordResult;
133
213
  };
134
214
  }
135
215
  let adminConfig = {
136
- events: false,
137
- renderCallback: this.renderCallback.bind(this),
216
+ events: this.events,
138
217
  dataServer: this.dataServer,
139
218
  authenticationCallback,
140
219
  app: this.app,
141
220
  appServerFactory: this.appServerFactory,
221
+ entities: this.adminEntities,
222
+ validator: new AdminManagerValidator(),
223
+ renderCallback: this.renderCallback.bind(this),
142
224
  secret: this.config.adminSecret,
143
225
  rootPath: this.config.adminPath,
144
- adminRoleId: 99,
145
- entities: this.entities
226
+ translations: AdminTranslations.appendTranslations(this.entitiesTranslations || {}),
227
+ adminFilesContents: await AdminTemplatesLoader.fetchAdminFilesContents(
228
+ TemplatesToPathMapper.map(this.adminTemplatesList, this.projectAdminTemplatesPath)
229
+ ),
230
+ mimeTypes: this.mimeTypes,
231
+ allowedExtensions: this.allowedExtensions,
232
+ adminRoleId: this.adminRoleId,
233
+ stylesFilePath: this.stylesFilePath,
234
+ scriptsFilePath: this.scriptsFilePath,
235
+ branding: {
236
+ companyName: this.companyName,
237
+ logo: this.logo,
238
+ favicon: this.favicon,
239
+ copyRight: await FileHandler.fetchFileContents(
240
+ FileHandler.joinPaths(this.projectAdminTemplatesPath, this.adminTemplatesList.defaultCopyRight)
241
+ )
242
+ }
146
243
  };
147
244
  this.adminManager = new AdminManager(adminConfig);
148
245
  await this.adminManager.setupAdmin();
@@ -157,14 +254,15 @@ class Manager
157
254
  return mustache.render(template, params);
158
255
  }
159
256
 
160
- async initializeStorefront()
257
+ async initializeFrontend()
161
258
  {
162
- this.storefront = new Storefront({
259
+ this.frontend = new Frontend({
163
260
  app: this.app,
164
261
  dataServer: this.dataServer,
165
- projectRoot: this.projectRoot
262
+ projectRoot: this.projectRoot,
263
+ appServerFactory: this.appServerFactory
166
264
  });
167
- return await this.storefront.initialize();
265
+ return await this.frontend.initialize();
168
266
  }
169
267
  }
170
268
 
@@ -0,0 +1,35 @@
1
+ /**
2
+ *
3
+ * Reldens - MimeTypes
4
+ *
5
+ */
6
+
7
+ module.exports.MimeTypes = {
8
+ audio: [
9
+ 'audio/aac',
10
+ 'audio/midi',
11
+ 'audio/x-midi',
12
+ 'audio/mpeg',
13
+ 'audio/ogg',
14
+ 'application/ogg',
15
+ 'audio/opus',
16
+ 'audio/wav',
17
+ 'audio/webm',
18
+ 'audio/3gpp2'
19
+ ],
20
+ image: [
21
+ 'image/bmp',
22
+ 'image/gif',
23
+ 'image/jpeg',
24
+ 'image/png',
25
+ 'image/svg+xml',
26
+ 'image/vnd.microsoft.icon',
27
+ 'image/tiff',
28
+ 'image/webp'
29
+ ],
30
+ text: [
31
+ 'application/json',
32
+ 'application/ld+json',
33
+ 'text/plain',
34
+ ]
35
+ };
@@ -8,10 +8,6 @@ module.exports.TemplatesList = {
8
8
  login: 'login.html',
9
9
  dashboard: 'dashboard.html',
10
10
  management: 'management.html',
11
- mapsWizard: 'maps-wizard.html',
12
- mapsWizardMapsSelection: 'maps-wizard-maps-selection.html',
13
- objectsImport: 'objects-import.html',
14
- skillsImport: 'skills-import.html',
15
11
  list: 'list.html',
16
12
  listContent: 'list-content.html',
17
13
  view: 'view.html',
@@ -41,10 +37,5 @@ module.exports.TemplatesList = {
41
37
  button: 'button.html',
42
38
  file: 'file.html'
43
39
  }
44
- },
45
- sections: {
46
- view: {
47
- rooms: 'rooms.html'
48
- }
49
40
  }
50
41
  };