@intranefr/superbackend 1.5.3 → 1.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/cookies.txt +6 -0
  2. package/cookies1.txt +6 -0
  3. package/cookies2.txt +6 -0
  4. package/cookies3.txt +6 -0
  5. package/cookies4.txt +5 -0
  6. package/cookies_old.txt +5 -0
  7. package/cookies_old_test.txt +6 -0
  8. package/cookies_super.txt +5 -0
  9. package/cookies_super_test.txt +6 -0
  10. package/cookies_test.txt +6 -0
  11. package/index.js +7 -0
  12. package/package.json +3 -1
  13. package/plugins/core-waiting-list-migration/README.md +118 -0
  14. package/plugins/core-waiting-list-migration/index.js +438 -0
  15. package/plugins/global-settings-presets/index.js +20 -0
  16. package/plugins/hello-cli/index.js +17 -0
  17. package/plugins/ui-components-seeder/components/suiAlert.js +212 -0
  18. package/plugins/ui-components-seeder/components/suiToast.js +186 -0
  19. package/plugins/ui-components-seeder/index.js +31 -0
  20. package/public/js/admin-ui-components-preview.js +281 -0
  21. package/public/js/admin-ui-components.js +408 -0
  22. package/public/js/llm-provider-model-picker.js +193 -0
  23. package/public/test-iframe-fix.html +63 -0
  24. package/public/test-iframe.html +14 -0
  25. package/src/admin/endpointRegistry.js +68 -0
  26. package/src/controllers/admin.controller.js +25 -5
  27. package/src/controllers/adminDataCleanup.controller.js +45 -0
  28. package/src/controllers/adminLlm.controller.js +0 -8
  29. package/src/controllers/adminLogin.controller.js +269 -0
  30. package/src/controllers/adminPlugins.controller.js +55 -0
  31. package/src/controllers/adminRegistry.controller.js +106 -0
  32. package/src/controllers/adminStats.controller.js +4 -4
  33. package/src/controllers/registry.controller.js +32 -0
  34. package/src/controllers/waitingList.controller.js +52 -74
  35. package/src/middleware/auth.js +71 -1
  36. package/src/middleware/rbac.js +62 -0
  37. package/src/middleware.js +480 -156
  38. package/src/models/GlobalSetting.js +11 -1
  39. package/src/models/UiComponent.js +2 -0
  40. package/src/models/User.js +1 -1
  41. package/src/routes/admin.routes.js +3 -3
  42. package/src/routes/adminAgents.routes.js +2 -2
  43. package/src/routes/adminAssets.routes.js +11 -11
  44. package/src/routes/adminBlog.routes.js +2 -2
  45. package/src/routes/adminBlogAi.routes.js +2 -2
  46. package/src/routes/adminBlogAutomation.routes.js +2 -2
  47. package/src/routes/adminCache.routes.js +2 -2
  48. package/src/routes/adminConsoleManager.routes.js +2 -2
  49. package/src/routes/adminCrons.routes.js +2 -2
  50. package/src/routes/adminDataCleanup.routes.js +26 -0
  51. package/src/routes/adminDbBrowser.routes.js +2 -2
  52. package/src/routes/adminEjsVirtual.routes.js +2 -2
  53. package/src/routes/adminFeatureFlags.routes.js +6 -6
  54. package/src/routes/adminHeadless.routes.js +2 -2
  55. package/src/routes/adminHealthChecks.routes.js +2 -2
  56. package/src/routes/adminI18n.routes.js +2 -2
  57. package/src/routes/adminJsonConfigs.routes.js +8 -8
  58. package/src/routes/adminLlm.routes.js +8 -8
  59. package/src/routes/adminLogin.routes.js +23 -0
  60. package/src/routes/adminMarkdowns.routes.js +3 -9
  61. package/src/routes/adminMigration.routes.js +12 -12
  62. package/src/routes/adminPages.routes.js +2 -2
  63. package/src/routes/adminPlugins.routes.js +15 -0
  64. package/src/routes/adminProxy.routes.js +2 -2
  65. package/src/routes/adminRateLimits.routes.js +8 -8
  66. package/src/routes/adminRbac.routes.js +2 -2
  67. package/src/routes/adminRegistry.routes.js +24 -0
  68. package/src/routes/adminScripts.routes.js +2 -2
  69. package/src/routes/adminSeoConfig.routes.js +10 -10
  70. package/src/routes/adminTelegram.routes.js +2 -2
  71. package/src/routes/adminTerminals.routes.js +2 -2
  72. package/src/routes/adminUiComponents.routes.js +2 -2
  73. package/src/routes/adminUploadNamespaces.routes.js +7 -7
  74. package/src/routes/blogInternal.routes.js +2 -2
  75. package/src/routes/experiments.routes.js +2 -2
  76. package/src/routes/formsAdmin.routes.js +6 -6
  77. package/src/routes/globalSettings.routes.js +8 -8
  78. package/src/routes/internalExperiments.routes.js +2 -2
  79. package/src/routes/notificationAdmin.routes.js +7 -7
  80. package/src/routes/orgAdmin.routes.js +16 -16
  81. package/src/routes/pages.routes.js +3 -3
  82. package/src/routes/registry.routes.js +11 -0
  83. package/src/routes/stripeAdmin.routes.js +12 -12
  84. package/src/routes/userAdmin.routes.js +7 -7
  85. package/src/routes/waitingListAdmin.routes.js +2 -2
  86. package/src/routes/workflows.routes.js +3 -3
  87. package/src/services/dataCleanup.service.js +286 -0
  88. package/src/services/jsonConfigs.service.js +262 -0
  89. package/src/services/plugins.service.js +348 -0
  90. package/src/services/registry.service.js +452 -0
  91. package/src/services/uiComponents.service.js +180 -0
  92. package/src/services/waitingListJson.service.js +401 -0
  93. package/src/utils/rbac/rightsRegistry.js +118 -0
  94. package/test-access.js +63 -0
  95. package/test-iframe-fix.html +63 -0
  96. package/test-iframe.html +14 -0
  97. package/views/admin-403.ejs +92 -0
  98. package/views/admin-dashboard-home.ejs +52 -2
  99. package/views/admin-dashboard.ejs +143 -2
  100. package/views/admin-data-cleanup.ejs +357 -0
  101. package/views/admin-login.ejs +286 -0
  102. package/views/admin-plugins-system.ejs +223 -0
  103. package/views/admin-ui-components.ejs +82 -402
  104. package/views/admin-users.ejs +207 -11
  105. package/views/partials/dashboard/nav-items.ejs +2 -0
  106. package/views/partials/llm-provider-model-picker.ejs +0 -161
package/src/middleware.js CHANGED
@@ -23,7 +23,10 @@ const mongoose = require("mongoose");
23
23
  const cors = require("cors");
24
24
  const fs = require("fs");
25
25
  const ejs = require("ejs");
26
- const { basicAuth } = require("./middleware/auth");
26
+ const session = require("express-session");
27
+ const MongoStore = require("connect-mongo");
28
+ const { adminSessionAuth } = require("./middleware/auth");
29
+ const { requireModuleAccess } = require("./middleware/rbac");
27
30
  const endpointRegistry = require("./admin/endpointRegistry");
28
31
  const {
29
32
  createFeatureFlagsEjsMiddleware,
@@ -40,6 +43,8 @@ const {
40
43
  requestIdMiddleware,
41
44
  } = require("./middleware/errorCapture");
42
45
  const rateLimiter = require("./services/rateLimiter.service");
46
+ const pluginsService = require("./services/plugins.service");
47
+ const telegramService = require("./services/telegram.service");
43
48
 
44
49
  let errorCaptureInitialized = false;
45
50
 
@@ -81,6 +86,10 @@ async function isConsoleManagerEnabled() {
81
86
  * @param {string} options.jwtSecret - JWT secret for authentication
82
87
  * @param {Object} options.dbConnection - Existing Mongoose connection
83
88
  * @param {boolean} options.skipBodyParser - Skip adding body parser middleware (default: false)
89
+ * @param {Object} options.telegram - Telegram configuration
90
+ * @param {boolean} options.telegram.enabled - Whether to enable Telegram bots (default: true)
91
+ * @param {Object} options.cron - Cron scheduler configuration
92
+ * @param {boolean} options.cron.enabled - Whether to enable cron scheduler (default: true)
84
93
  * @returns {express.Router} Configured Express router
85
94
  */
86
95
  function createMiddleware(options = {}) {
@@ -88,6 +97,66 @@ function createMiddleware(options = {}) {
88
97
  const adminPath = options.adminPath || "/admin";
89
98
  const pagesPrefix = options.pagesPrefix || "/";
90
99
 
100
+ const bootstrapPluginsRuntime = async () => {
101
+ try {
102
+ const superbackend = globalThis.superbackend || globalThis.saasbackend || {};
103
+ await pluginsService.bootstrap({
104
+ context: {
105
+ services: superbackend.services || {},
106
+ helpers: superbackend.helpers || {},
107
+ },
108
+ });
109
+ const pluginServices = pluginsService.getExposedServices();
110
+ const pluginHelpers = pluginsService.getExposedHelpers();
111
+ if (superbackend.services && typeof superbackend.services === "object") {
112
+ superbackend.services.pluginsRuntime = pluginServices;
113
+ }
114
+ if (superbackend.helpers && typeof superbackend.helpers === "object") {
115
+ superbackend.helpers.pluginsRuntime = pluginHelpers;
116
+ }
117
+ } catch (error) {
118
+ console.error("Failed to bootstrap plugins runtime:", error);
119
+ }
120
+ };
121
+
122
+ // Debug: Log received options
123
+ console.log("[Middleware Debug] Received options:", {
124
+ telegramEnabled: options.telegram?.enabled,
125
+ cronEnabled: options.cron?.enabled
126
+ });
127
+
128
+ router.get(`${adminPath}/plugins-system`, requireModuleAccessWithIframe('plugins', 'read'), (req, res) => {
129
+ const templatePath = path.join(
130
+ __dirname,
131
+ "..",
132
+ "views",
133
+ "admin-plugins-system.ejs",
134
+ );
135
+ fs.readFile(templatePath, "utf8", (err, template) => {
136
+ if (err) {
137
+ console.error("Error reading template:", err);
138
+ return res.status(500).send("Error loading page");
139
+ }
140
+ try {
141
+ const html = ejs.render(
142
+ template,
143
+ {
144
+ baseUrl: req.baseUrl,
145
+ adminPath,
146
+ isIframe: req.isIframe || false
147
+ },
148
+ {
149
+ filename: templatePath,
150
+ },
151
+ );
152
+ res.send(html);
153
+ } catch (renderErr) {
154
+ console.error("Error rendering template:", renderErr);
155
+ res.status(500).send("Error rendering page");
156
+ }
157
+ });
158
+ });
159
+
91
160
  const normalizeBasePath = (value) => {
92
161
  const v = String(value || "").trim();
93
162
  if (!v) return "/files";
@@ -161,22 +230,44 @@ function createMiddleware(options = {}) {
161
230
  maxPoolSize: 10,
162
231
  };
163
232
 
164
- const telegramService = require("./services/telegram.service");
165
-
166
233
  // Return a promise that resolves when connection is established
167
234
  const connectionPromise = mongoose
168
235
  .connect(mongoUri, connectionOptions)
169
236
  .then(async () => {
170
237
  console.log("✅ Middleware: Connected to MongoDB");
171
- // Start cron scheduler after DB connection
172
- await cronScheduler.start();
173
- await healthChecksScheduler.start();
174
- await healthChecksBootstrap.bootstrap();
175
- await blogCronsBootstrap.bootstrap();
176
- await require("./services/experimentsCronsBootstrap.service").bootstrap();
177
238
 
178
- // Initialize Telegram bots
179
- await telegramService.init();
239
+ // Start cron scheduler after DB connection (only if enabled)
240
+ if (options.cron?.enabled !== false) {
241
+ await cronScheduler.start();
242
+ await healthChecksScheduler.start();
243
+ await healthChecksBootstrap.bootstrap();
244
+ await blogCronsBootstrap.bootstrap();
245
+ await require("./services/experimentsCronsBootstrap.service").bootstrap();
246
+ } else {
247
+ console.log("🔍 Cron scheduler disabled - cron.enabled:", options.cron?.enabled);
248
+ }
249
+
250
+ // Initialize Telegram bots (check telegram config)
251
+ const telegramEnabled = options.telegram?.enabled !== false;
252
+ if (telegramEnabled) {
253
+ const telegramInitializer =
254
+ (telegramService && typeof telegramService.initialize === "function"
255
+ ? telegramService.initialize.bind(telegramService)
256
+ : null) ||
257
+ (telegramService && typeof telegramService.init === "function"
258
+ ? telegramService.init.bind(telegramService)
259
+ : null);
260
+
261
+ if (telegramInitializer) {
262
+ await telegramInitializer();
263
+ } else {
264
+ console.warn("⚠️ Telegram service has no initialize/init method; skipping startup");
265
+ }
266
+ } else {
267
+ console.log("🔍 Telegram bots disabled - telegram.enabled:", options.telegram?.enabled);
268
+ }
269
+
270
+ await bootstrapPluginsRuntime();
180
271
 
181
272
  // Console manager is already initialized early in the middleware
182
273
  console.log("[Console Manager] MongoDB connection established");
@@ -188,7 +279,7 @@ const telegramService = require("./services/telegram.service");
188
279
  return false;
189
280
  });
190
281
 
191
- router.get(`${adminPath}/health-checks`, basicAuth, (req, res) => {
282
+ router.get(`${adminPath}/health-checks`, requireModuleAccessWithIframe('health-checks', 'read'), (req, res) => {
192
283
  const templatePath = path.join(
193
284
  __dirname,
194
285
  "..",
@@ -206,6 +297,7 @@ const telegramService = require("./services/telegram.service");
206
297
  {
207
298
  baseUrl: req.baseUrl,
208
299
  adminPath,
300
+ isIframe: req.isIframe || false
209
301
  },
210
302
  {
211
303
  filename: templatePath,
@@ -219,7 +311,39 @@ const telegramService = require("./services/telegram.service");
219
311
  });
220
312
  });
221
313
 
222
- router.get(`${adminPath}/console-manager`, basicAuth, (req, res) => {
314
+ router.get(`${adminPath}/data-cleanup`, requireModuleAccessWithIframe('data-cleanup', 'read'), (req, res) => {
315
+ const templatePath = path.join(
316
+ __dirname,
317
+ "..",
318
+ "views",
319
+ "admin-data-cleanup.ejs",
320
+ );
321
+ fs.readFile(templatePath, "utf8", (err, template) => {
322
+ if (err) {
323
+ console.error("Error reading template:", err);
324
+ return res.status(500).send("Error loading page");
325
+ }
326
+ try {
327
+ const html = ejs.render(
328
+ template,
329
+ {
330
+ baseUrl: req.baseUrl,
331
+ adminPath,
332
+ isIframe: req.isIframe || false
333
+ },
334
+ {
335
+ filename: templatePath,
336
+ },
337
+ );
338
+ res.send(html);
339
+ } catch (renderErr) {
340
+ console.error("Error rendering template:", renderErr);
341
+ res.status(500).send("Error rendering page");
342
+ }
343
+ });
344
+ });
345
+
346
+ router.get(`${adminPath}/console-manager`, requireModuleAccessWithIframe('console-manager', 'read'), (req, res) => {
223
347
  const templatePath = path.join(
224
348
  __dirname,
225
349
  "..",
@@ -237,6 +361,7 @@ const telegramService = require("./services/telegram.service");
237
361
  {
238
362
  baseUrl: req.baseUrl,
239
363
  adminPath,
364
+ isIframe: req.isIframe || false
240
365
  },
241
366
  {
242
367
  filename: templatePath,
@@ -254,25 +379,56 @@ const telegramService = require("./services/telegram.service");
254
379
  router.connectionPromise = connectionPromise;
255
380
  } else if (mongoose.connection.readyState === 1) {
256
381
  console.log("✅ Middleware: Using existing MongoDB connection");
257
- // Start cron scheduler for existing connection
258
- cronScheduler.start().catch((err) => {
259
- console.error("Failed to start cron scheduler:", err);
260
- });
261
- healthChecksScheduler.start().catch((err) => {
262
- console.error("Failed to start health checks scheduler:", err);
263
- });
264
- healthChecksBootstrap.bootstrap().catch((err) => {
265
- console.error("Failed to bootstrap health checks:", err);
266
- });
267
- blogCronsBootstrap.bootstrap().catch((err) => {
268
- console.error("Failed to bootstrap blog crons:", err);
269
- });
270
-
271
- require("./services/experimentsCronsBootstrap.service")
272
- .bootstrap()
273
- .catch((err) => {
274
- console.error("Failed to bootstrap experiments crons:", err);
382
+
383
+ // Start cron scheduler for existing connection (only if enabled)
384
+ if (options.cron?.enabled !== false) {
385
+ cronScheduler.start().catch((err) => {
386
+ console.error("Failed to start cron scheduler:", err);
387
+ });
388
+ healthChecksScheduler.start().catch((err) => {
389
+ console.error("Failed to start health checks scheduler:", err);
275
390
  });
391
+ healthChecksBootstrap.bootstrap().catch((err) => {
392
+ console.error("Failed to bootstrap health checks:", err);
393
+ });
394
+ blogCronsBootstrap.bootstrap().catch((err) => {
395
+ console.error("Failed to bootstrap blog crons:", err);
396
+ });
397
+
398
+ require("./services/experimentsCronsBootstrap.service")
399
+ .bootstrap()
400
+ .catch((err) => {
401
+ console.error("Failed to bootstrap experiments crons:", err);
402
+ });
403
+ } else {
404
+ console.log("🔍 Cron scheduler disabled - cron.enabled:", options.cron?.enabled, "(existing connection)");
405
+ }
406
+
407
+ // Initialize Telegram bots for existing connection (check telegram config)
408
+ const telegramEnabled = options.telegram?.enabled !== false;
409
+ if (telegramEnabled) {
410
+ const telegramInitializer =
411
+ (telegramService && typeof telegramService.initialize === "function"
412
+ ? telegramService.initialize.bind(telegramService)
413
+ : null) ||
414
+ (telegramService && typeof telegramService.init === "function"
415
+ ? telegramService.init.bind(telegramService)
416
+ : null);
417
+
418
+ if (!telegramInitializer) {
419
+ console.warn("⚠️ Telegram service has no initialize/init method; skipping startup (existing connection)");
420
+ } else {
421
+ telegramInitializer().catch(err => {
422
+ console.error("Failed to initialize Telegram service (existing connection):", err);
423
+ });
424
+ }
425
+ } else {
426
+ console.log("🔍 Telegram bots disabled - telegram.enabled:", options.telegram?.enabled, "(existing connection)");
427
+ }
428
+
429
+ bootstrapPluginsRuntime().catch((err) => {
430
+ console.error("Failed to bootstrap plugins runtime (existing connection):", err);
431
+ });
276
432
 
277
433
  // Initialize console manager AFTER database is already connected
278
434
  if (process.env.NODE_ENV !== "test" && !process.env.JEST_WORKER_ID) {
@@ -367,10 +523,34 @@ const telegramService = require("./services/telegram.service");
367
523
  router.use(express.urlencoded({ extended: true }));
368
524
  }
369
525
 
526
+ // Session middleware for admin authentication
527
+ const sessionMiddleware = session({
528
+ secret: process.env.SESSION_SECRET || 'superbackend-session-secret-fallback',
529
+ resave: false,
530
+ saveUninitialized: false,
531
+ cookie: {
532
+ secure: process.env.NODE_ENV === 'production',
533
+ httpOnly: true,
534
+ maxAge: 24 * 60 * 60 * 1000, // 24 hours
535
+ sameSite: 'lax'
536
+ },
537
+ store: MongoStore.create({
538
+ mongoUrl: options.mongodbUri || process.env.MONGODB_URI,
539
+ collectionName: 'admin_sessions',
540
+ ttl: 24 * 60 * 60 // 24 hours in seconds
541
+ }),
542
+ name: 'superbackend.admin.session'
543
+ });
544
+
545
+ router.use(sessionMiddleware);
546
+
370
547
  router.use(requestIdMiddleware);
371
548
 
372
549
  router.use("/api", rateLimiter.limit("globalApiLimiter"));
373
550
 
551
+ // Serve public static files with /public prefix (for admin UI components)
552
+ router.use("/public", express.static(path.join(__dirname, "..", "public")));
553
+
374
554
  // Serve public static files (e.g. /og/og-default.png)
375
555
  router.use(express.static(path.join(__dirname, "..", "public")));
376
556
 
@@ -448,7 +628,7 @@ const telegramService = require("./services/telegram.service");
448
628
  require("./routes/waitingListAdmin.routes"),
449
629
  );
450
630
  router.use("/api/admin/orgs", require("./routes/orgAdmin.routes"));
451
- router.use("/api/admin/users", require("./routes/userAdmin.routes"));
631
+ router.use("/api/admin/users", requireModuleAccessWithIframe('users', 'read'), require("./routes/userAdmin.routes"));
452
632
  router.use("/api/admin/rbac", require("./routes/adminRbac.routes"));
453
633
  router.use(
454
634
  "/api/admin/notifications",
@@ -460,11 +640,111 @@ const telegramService = require("./services/telegram.service");
460
640
  const adminStatsController = require("./controllers/adminStats.controller");
461
641
  router.get(
462
642
  "/api/admin/stats/overview",
463
- basicAuth,
643
+ adminSessionAuth,
464
644
  adminStatsController.getOverviewStats,
465
645
  );
466
646
 
467
- router.get(`${adminPath}/stats/dashboard-home`, basicAuth, (req, res) => {
647
+ // Middleware to check if request is from authenticated parent iframe
648
+ function checkIframeAuth(req, res, next) {
649
+ const referer = req.get('Referer');
650
+ const origin = req.get('Origin');
651
+ const adminPath = req.adminPath || '/admin';
652
+
653
+ // Check for iframe token parameter (more reliable than referer)
654
+ const iframeToken = req.query.iframe_token;
655
+ if (iframeToken && iframeToken === 'authenticated') {
656
+ req.isIframe = true;
657
+ return next();
658
+ }
659
+
660
+ // Fallback to referer/origin check
661
+ const isValidReferer = referer && referer.includes(adminPath);
662
+ const isValidOrigin = origin && origin.includes(req.hostname);
663
+
664
+ if (isValidReferer || isValidOrigin) {
665
+ req.isIframe = true;
666
+ return next();
667
+ }
668
+
669
+ // If not from iframe, require normal authentication
670
+ return adminSessionAuth(req, res, next);
671
+ }
672
+
673
+ // Combined middleware for iframe authentication + module access
674
+ function requireModuleAccessWithIframe(moduleId, action = 'read') {
675
+ return async (req, res, next) => {
676
+ try {
677
+ // Check for iframe authentication first
678
+ const referer = req.get('Referer');
679
+ const origin = req.get('Origin');
680
+ const adminPath = req.adminPath || '/admin';
681
+ const iframeToken = req.query.iframe_token;
682
+
683
+ const isValidIframe = (iframeToken && iframeToken === 'authenticated') ||
684
+ (referer && referer.includes(adminPath)) ||
685
+ (origin && origin.includes(req.hostname));
686
+
687
+ if (isValidIframe) {
688
+ req.isIframe = true;
689
+ // For iframe requests, we'll allow access but mark it as iframe context
690
+ return next();
691
+ }
692
+
693
+ // Check for basic auth superadmin bypass
694
+ if (isBasicAuthSuperAdmin(req)) {
695
+ return next();
696
+ }
697
+
698
+ // Get user ID from session
699
+ const userId = req.session?.authData?.userId;
700
+ if (!userId) {
701
+ return res.redirect(`${req.adminPath || '/admin'}/login`);
702
+ }
703
+
704
+ // Check RBAC permission for specific module
705
+ const hasAccess = await rbacService.checkRight({
706
+ userId,
707
+ orgId: null, // Global admin permissions
708
+ right: `admin_panel__${moduleId}:${action}`
709
+ });
710
+
711
+ if (!hasAccess.allowed) {
712
+ // For API routes, return JSON error
713
+ if (req.path.startsWith('/api/')) {
714
+ return res.status(403).json({
715
+ error: 'Access denied',
716
+ reason: hasAccess.reason,
717
+ required: `admin_panel__${moduleId}:${action}`,
718
+ moduleId,
719
+ action
720
+ });
721
+ }
722
+
723
+ // For page routes, render 403 page
724
+ return res.status(403).render('admin-403', {
725
+ moduleId,
726
+ action,
727
+ required: `admin_panel__${moduleId}:${action}`,
728
+ reason: hasAccess.reason,
729
+ user: req.session.authData,
730
+ adminPath: req.adminPath || '/admin'
731
+ });
732
+ }
733
+
734
+ next();
735
+ } catch (error) {
736
+ console.error('Module access check error:', error);
737
+
738
+ if (req.path.startsWith('/api/')) {
739
+ return res.status(500).json({ error: 'Access check failed' });
740
+ } else {
741
+ return res.status(500).send('Access check failed');
742
+ }
743
+ }
744
+ };
745
+ }
746
+
747
+ router.get(`${adminPath}/stats/dashboard-home`, checkIframeAuth, (req, res) => {
468
748
  const templatePath = path.join(
469
749
  __dirname,
470
750
  "..",
@@ -479,7 +759,11 @@ const telegramService = require("./services/telegram.service");
479
759
  try {
480
760
  const html = ejs.render(
481
761
  template,
482
- { baseUrl: req.baseUrl, adminPath },
762
+ {
763
+ baseUrl: req.baseUrl,
764
+ adminPath,
765
+ isIframe: req.isIframe || false
766
+ },
483
767
  { filename: templatePath },
484
768
  );
485
769
  res.send(html);
@@ -490,7 +774,7 @@ const telegramService = require("./services/telegram.service");
490
774
  });
491
775
  });
492
776
 
493
- router.get(`${adminPath}/experiments`, basicAuth, (req, res) => {
777
+ router.get(`${adminPath}/experiments`, requireModuleAccessWithIframe('experiments', 'read'), (req, res) => {
494
778
  const templatePath = path.join(
495
779
  __dirname,
496
780
  "..",
@@ -508,6 +792,7 @@ const telegramService = require("./services/telegram.service");
508
792
  {
509
793
  baseUrl: req.baseUrl,
510
794
  adminPath,
795
+ isIframe: req.isIframe || false
511
796
  },
512
797
  {
513
798
  filename: templatePath,
@@ -521,7 +806,7 @@ const telegramService = require("./services/telegram.service");
521
806
  });
522
807
  });
523
808
 
524
- router.get(`${adminPath}/rbac`, basicAuth, (req, res) => {
809
+ router.get(`${adminPath}/rbac`, requireModuleAccessWithIframe('rbac', 'read'), (req, res) => {
525
810
  const templatePath = path.join(__dirname, "..", "views", "admin-rbac.ejs");
526
811
  fs.readFile(templatePath, "utf8", (err, template) => {
527
812
  if (err) {
@@ -534,6 +819,7 @@ const telegramService = require("./services/telegram.service");
534
819
  {
535
820
  baseUrl: req.baseUrl,
536
821
  adminPath,
822
+ isIframe: req.isIframe || false
537
823
  },
538
824
  {
539
825
  filename: templatePath,
@@ -547,7 +833,7 @@ const telegramService = require("./services/telegram.service");
547
833
  });
548
834
  });
549
835
 
550
- router.get(`${adminPath}/terminals`, basicAuth, (req, res) => {
836
+ router.get(`${adminPath}/terminals`, requireModuleAccessWithIframe('terminals', 'read'), (req, res) => {
551
837
  const templatePath = path.join(
552
838
  __dirname,
553
839
  "..",
@@ -566,6 +852,7 @@ const telegramService = require("./services/telegram.service");
566
852
  baseUrl: req.baseUrl,
567
853
  adminPath,
568
854
  endpointRegistry,
855
+ isIframe: req.isIframe || false
569
856
  },
570
857
  {
571
858
  filename: templatePath,
@@ -579,7 +866,7 @@ const telegramService = require("./services/telegram.service");
579
866
  });
580
867
  });
581
868
 
582
- router.get(`${adminPath}/scripts`, basicAuth, (req, res) => {
869
+ router.get(`${adminPath}/scripts`, requireModuleAccessWithIframe('scripts', 'read'), (req, res) => {
583
870
  const templatePath = path.join(
584
871
  __dirname,
585
872
  "..",
@@ -598,6 +885,7 @@ const telegramService = require("./services/telegram.service");
598
885
  baseUrl: req.baseUrl,
599
886
  adminPath,
600
887
  endpointRegistry,
888
+ isIframe: req.isIframe || false
601
889
  },
602
890
  {
603
891
  filename: templatePath,
@@ -611,7 +899,7 @@ const telegramService = require("./services/telegram.service");
611
899
  });
612
900
  });
613
901
 
614
- router.get(`${adminPath}/crons`, basicAuth, (req, res) => {
902
+ router.get(`${adminPath}/crons`, requireModuleAccessWithIframe('crons', 'read'), (req, res) => {
615
903
  const templatePath = path.join(__dirname, "..", "views", "admin-crons.ejs");
616
904
  fs.readFile(templatePath, "utf8", (err, template) => {
617
905
  if (err) {
@@ -624,6 +912,7 @@ const telegramService = require("./services/telegram.service");
624
912
  {
625
913
  baseUrl: req.baseUrl,
626
914
  adminPath,
915
+ isIframe: req.isIframe || false
627
916
  },
628
917
  {
629
918
  filename: templatePath,
@@ -637,7 +926,7 @@ const telegramService = require("./services/telegram.service");
637
926
  });
638
927
  });
639
928
 
640
- router.get(`${adminPath}/cache`, basicAuth, (req, res) => {
929
+ router.get(`${adminPath}/cache`, requireModuleAccessWithIframe('cache', 'read'), (req, res) => {
641
930
  const templatePath = path.join(__dirname, "..", "views", "admin-cache.ejs");
642
931
  fs.readFile(templatePath, "utf8", (err, template) => {
643
932
  if (err) {
@@ -650,6 +939,7 @@ const telegramService = require("./services/telegram.service");
650
939
  {
651
940
  baseUrl: req.baseUrl,
652
941
  adminPath,
942
+ isIframe: req.isIframe || false
653
943
  },
654
944
  {
655
945
  filename: templatePath,
@@ -663,7 +953,7 @@ const telegramService = require("./services/telegram.service");
663
953
  });
664
954
  });
665
955
 
666
- router.get(`${adminPath}/db-browser`, basicAuth, (req, res) => {
956
+ router.get(`${adminPath}/db-browser`, requireModuleAccessWithIframe('db-browser', 'read'), (req, res) => {
667
957
  const templatePath = path.join(
668
958
  __dirname,
669
959
  "..",
@@ -681,6 +971,7 @@ const telegramService = require("./services/telegram.service");
681
971
  {
682
972
  baseUrl: req.baseUrl,
683
973
  adminPath,
974
+ isIframe: req.isIframe || false
684
975
  },
685
976
  {
686
977
  filename: templatePath,
@@ -694,7 +985,7 @@ const telegramService = require("./services/telegram.service");
694
985
  });
695
986
  });
696
987
 
697
- router.get(`${adminPath}/telegram`, basicAuth, (req, res) => {
988
+ router.get(`${adminPath}/telegram`, requireModuleAccessWithIframe('telegram', 'read'), (req, res) => {
698
989
  const templatePath = path.join(
699
990
  __dirname,
700
991
  "..",
@@ -712,6 +1003,7 @@ const telegramService = require("./services/telegram.service");
712
1003
  {
713
1004
  baseUrl: req.baseUrl,
714
1005
  adminPath,
1006
+ isIframe: req.isIframe || false
715
1007
  },
716
1008
  {
717
1009
  filename: templatePath,
@@ -725,7 +1017,7 @@ const telegramService = require("./services/telegram.service");
725
1017
  });
726
1018
  });
727
1019
 
728
- router.get(`${adminPath}/agents`, basicAuth, (req, res) => {
1020
+ router.get(`${adminPath}/agents`, requireModuleAccessWithIframe('agents', 'read'), (req, res) => {
729
1021
  const templatePath = path.join(
730
1022
  __dirname,
731
1023
  "..",
@@ -743,6 +1035,7 @@ const telegramService = require("./services/telegram.service");
743
1035
  {
744
1036
  baseUrl: req.baseUrl,
745
1037
  adminPath,
1038
+ isIframe: req.isIframe || false
746
1039
  },
747
1040
  {
748
1041
  filename: templatePath,
@@ -796,6 +1089,10 @@ const telegramService = require("./services/telegram.service");
796
1089
  "/api/admin/db-browser",
797
1090
  require("./routes/adminDbBrowser.routes"),
798
1091
  );
1092
+ router.use(
1093
+ "/api/admin/data-cleanup",
1094
+ require("./routes/adminDataCleanup.routes"),
1095
+ );
799
1096
  router.use("/api/admin/terminals", require("./routes/adminTerminals.routes"));
800
1097
  router.use("/api/admin/experiments", require("./routes/adminExperiments.routes"));
801
1098
  router.use("/api/admin/assets", require("./routes/adminAssets.routes"));
@@ -810,17 +1107,19 @@ const telegramService = require("./services/telegram.service");
810
1107
  router.use("/api/admin/migration", require("./routes/adminMigration.routes"));
811
1108
  router.use(
812
1109
  "/api/admin/errors",
813
- basicAuth,
1110
+ adminSessionAuth,
814
1111
  require("./routes/adminErrors.routes"),
815
1112
  );
816
1113
  router.use(
817
1114
  "/api/admin/audit",
818
- basicAuth,
1115
+ requireModuleAccessWithIframe('audit', 'read'),
819
1116
  require("./routes/adminAudit.routes"),
820
1117
  );
821
1118
  router.use("/api/admin/llm", require("./routes/adminLlm.routes"));
822
1119
  router.use("/api/admin/telegram", require("./routes/adminTelegram.routes"));
823
1120
  router.use("/api/admin/agents", require("./routes/adminAgents.routes"));
1121
+ router.use("/api/admin/registries", require("./routes/adminRegistry.routes"));
1122
+ router.use("/api/admin/plugins", require("./routes/adminPlugins.routes"));
824
1123
  router.use(
825
1124
  "/api/admin/ejs-virtual",
826
1125
  require("./routes/adminEjsVirtual.routes"),
@@ -829,7 +1128,7 @@ const telegramService = require("./services/telegram.service");
829
1128
  router.use("/api/admin", require("./routes/adminBlog.routes"));
830
1129
  router.use("/api/admin", require("./routes/adminBlogAi.routes"));
831
1130
  router.use("/api/admin", require("./routes/adminBlogAutomation.routes"));
832
- router.use("/api/admin/workflows", basicAuth, require("./routes/workflows.routes"));
1131
+ router.use("/api/admin/workflows", adminSessionAuth, require("./routes/workflows.routes"));
833
1132
  router.use("/w", require("./routes/workflowWebhook.routes"));
834
1133
  router.use("/api/webhooks", require("./routes/webhook.routes"));
835
1134
  router.use("/api/settings", require("./routes/globalSettings.routes"));
@@ -847,6 +1146,7 @@ const telegramService = require("./services/telegram.service");
847
1146
  router.use("/api/error-tracking", require("./routes/errorTracking.routes"));
848
1147
  router.use("/api/ui-components", require("./routes/uiComponentsPublic.routes"));
849
1148
  router.use("/api/rbac", require("./routes/rbac.routes"));
1149
+ router.use("/registry", require("./routes/registry.routes"));
850
1150
  router.use("/api/file-manager", require("./routes/fileManager.routes"));
851
1151
  router.use("/api/experiments", require("./routes/experiments.routes"));
852
1152
 
@@ -868,8 +1168,14 @@ const telegramService = require("./services/telegram.service");
868
1168
  // Public assets proxy
869
1169
  router.use("/public/assets", require("./routes/publicAssets.routes"));
870
1170
 
871
- // Admin dashboard (polished view)
872
- router.get(adminPath, basicAuth, (req, res) => {
1171
+ // Admin login routes (no authentication required)
1172
+ router.use(`${adminPath}`, (req, res, next) => {
1173
+ req.adminPath = adminPath;
1174
+ next();
1175
+ }, require("./routes/adminLogin.routes"));
1176
+
1177
+ // Admin dashboard (redirect to login if not authenticated)
1178
+ router.get(adminPath, adminSessionAuth, (req, res) => {
873
1179
  const templatePath = path.join(
874
1180
  __dirname,
875
1181
  "..",
@@ -884,7 +1190,7 @@ const telegramService = require("./services/telegram.service");
884
1190
  try {
885
1191
  const html = ejs.render(
886
1192
  template,
887
- { baseUrl: req.baseUrl, adminPath },
1193
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
888
1194
  { filename: templatePath },
889
1195
  );
890
1196
  res.send(html);
@@ -895,8 +1201,8 @@ const telegramService = require("./services/telegram.service");
895
1201
  });
896
1202
  });
897
1203
 
898
- // Admin technical API test page (protected by basic auth)
899
- router.get(`${adminPath}/api/test`, basicAuth, (req, res) => {
1204
+ // Admin technical API test page (protected by session auth)
1205
+ router.get(`${adminPath}/api/test`, adminSessionAuth, (req, res) => {
900
1206
  const templatePath = path.join(__dirname, "..", "views", "admin-test.ejs");
901
1207
  fs.readFile(templatePath, "utf8", (err, template) => {
902
1208
  if (err) {
@@ -910,6 +1216,7 @@ const telegramService = require("./services/telegram.service");
910
1216
  baseUrl: req.baseUrl,
911
1217
  adminPath,
912
1218
  endpointRegistry,
1219
+ isIframe: req.isIframe || false,
913
1220
  },
914
1221
  {
915
1222
  filename: templatePath,
@@ -923,7 +1230,7 @@ const telegramService = require("./services/telegram.service");
923
1230
  });
924
1231
  });
925
1232
 
926
- router.get(`${adminPath}/migration`, basicAuth, (req, res) => {
1233
+ router.get(`${adminPath}/migration`, requireModuleAccessWithIframe('migration', 'read'), (req, res) => {
927
1234
  const templatePath = path.join(
928
1235
  __dirname,
929
1236
  "..",
@@ -941,7 +1248,7 @@ const telegramService = require("./services/telegram.service");
941
1248
  {
942
1249
  baseUrl: req.baseUrl,
943
1250
  adminPath,
944
- endpointRegistry,
1251
+ isIframe: req.isIframe || false
945
1252
  },
946
1253
  {
947
1254
  filename: templatePath,
@@ -956,7 +1263,7 @@ const telegramService = require("./services/telegram.service");
956
1263
  });
957
1264
 
958
1265
  // Admin LLM/AI page (protected by basic auth)
959
- router.get(`${adminPath}/admin-llm`, basicAuth, (req, res) => {
1266
+ router.get(`${adminPath}/admin-llm`, requireModuleAccessWithIframe('admin-llm', 'read'), (req, res) => {
960
1267
  const templatePath = path.join(__dirname, "..", "views", "admin-llm.ejs");
961
1268
  fs.readFile(templatePath, "utf8", (err, template) => {
962
1269
  if (err) {
@@ -969,6 +1276,7 @@ const telegramService = require("./services/telegram.service");
969
1276
  {
970
1277
  baseUrl: req.baseUrl,
971
1278
  adminPath,
1279
+ isIframe: req.isIframe || false
972
1280
  },
973
1281
  {
974
1282
  filename: templatePath,
@@ -982,7 +1290,7 @@ const telegramService = require("./services/telegram.service");
982
1290
  });
983
1291
  });
984
1292
 
985
- router.get(`${adminPath}/workflows/:id`, basicAuth, (req, res) => {
1293
+ router.get(`${adminPath}/workflows/:id`, adminSessionAuth, (req, res) => {
986
1294
  const templatePath = path.join(
987
1295
  __dirname,
988
1296
  "..",
@@ -997,7 +1305,7 @@ const telegramService = require("./services/telegram.service");
997
1305
  try {
998
1306
  const html = ejs.render(
999
1307
  template,
1000
- { baseUrl: req.baseUrl, adminPath },
1308
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1001
1309
  { filename: templatePath },
1002
1310
  );
1003
1311
  res.send(html);
@@ -1008,7 +1316,7 @@ const telegramService = require("./services/telegram.service");
1008
1316
  });
1009
1317
  });
1010
1318
 
1011
- router.get(`${adminPath}/pages`, basicAuth, (req, res) => {
1319
+ router.get(`${adminPath}/pages`, requireModuleAccessWithIframe('pages', 'read'), (req, res) => {
1012
1320
  const templatePath = path.join(__dirname, "..", "views", "admin-pages.ejs");
1013
1321
  fs.readFile(templatePath, "utf8", (err, template) => {
1014
1322
  if (err) {
@@ -1021,6 +1329,7 @@ const telegramService = require("./services/telegram.service");
1021
1329
  {
1022
1330
  baseUrl: req.baseUrl,
1023
1331
  adminPath,
1332
+ isIframe: req.isIframe || false
1024
1333
  },
1025
1334
  {
1026
1335
  filename: templatePath,
@@ -1034,7 +1343,7 @@ const telegramService = require("./services/telegram.service");
1034
1343
  });
1035
1344
  });
1036
1345
 
1037
- router.get(`${adminPath}/blog`, basicAuth, (req, res) => {
1346
+ router.get(`${adminPath}/blog`, requireModuleAccessWithIframe('blog', 'read'), (req, res) => {
1038
1347
  const templatePath = path.join(__dirname, "..", "views", "admin-blog.ejs");
1039
1348
  fs.readFile(templatePath, "utf8", (err, template) => {
1040
1349
  if (err) {
@@ -1044,7 +1353,7 @@ const telegramService = require("./services/telegram.service");
1044
1353
  try {
1045
1354
  const html = ejs.render(
1046
1355
  template,
1047
- { baseUrl: req.baseUrl, adminPath },
1356
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1048
1357
  { filename: templatePath },
1049
1358
  );
1050
1359
  res.send(html);
@@ -1055,7 +1364,7 @@ const telegramService = require("./services/telegram.service");
1055
1364
  });
1056
1365
  });
1057
1366
 
1058
- router.get(`${adminPath}/blog-automation`, basicAuth, (req, res) => {
1367
+ router.get(`${adminPath}/blog-automation`, requireModuleAccessWithIframe('blog-automation', 'read'), (req, res) => {
1059
1368
  const templatePath = path.join(
1060
1369
  __dirname,
1061
1370
  "..",
@@ -1070,7 +1379,7 @@ const telegramService = require("./services/telegram.service");
1070
1379
  try {
1071
1380
  const html = ejs.render(
1072
1381
  template,
1073
- { baseUrl: req.baseUrl, adminPath },
1382
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1074
1383
  { filename: templatePath },
1075
1384
  );
1076
1385
  res.send(html);
@@ -1081,7 +1390,7 @@ const telegramService = require("./services/telegram.service");
1081
1390
  });
1082
1391
  });
1083
1392
 
1084
- router.get(`${adminPath}/blog/new`, basicAuth, (req, res) => {
1393
+ router.get(`${adminPath}/blog/new`, requireModuleAccessWithIframe('blog', 'read'), (req, res) => {
1085
1394
  const templatePath = path.join(
1086
1395
  __dirname,
1087
1396
  "..",
@@ -1096,7 +1405,7 @@ const telegramService = require("./services/telegram.service");
1096
1405
  try {
1097
1406
  const html = ejs.render(
1098
1407
  template,
1099
- { baseUrl: req.baseUrl, adminPath, postId: "", mode: "new" },
1408
+ { baseUrl: req.baseUrl, adminPath, postId: "", mode: "new", isIframe: req.isIframe || false },
1100
1409
  { filename: templatePath },
1101
1410
  );
1102
1411
  res.send(html);
@@ -1107,7 +1416,7 @@ const telegramService = require("./services/telegram.service");
1107
1416
  });
1108
1417
  });
1109
1418
 
1110
- router.get(`${adminPath}/blog/edit/:id`, basicAuth, (req, res) => {
1419
+ router.get(`${adminPath}/blog/edit/:id`, requireModuleAccessWithIframe('blog', 'read'), (req, res) => {
1111
1420
  const templatePath = path.join(
1112
1421
  __dirname,
1113
1422
  "..",
@@ -1127,6 +1436,7 @@ const telegramService = require("./services/telegram.service");
1127
1436
  adminPath,
1128
1437
  postId: String(req.params.id || ""),
1129
1438
  mode: "edit",
1439
+ isIframe: req.isIframe || false,
1130
1440
  },
1131
1441
  { filename: templatePath },
1132
1442
  );
@@ -1138,38 +1448,39 @@ const telegramService = require("./services/telegram.service");
1138
1448
  });
1139
1449
  });
1140
1450
 
1141
- router.get(`${adminPath}/file-manager`, basicAuth, (req, res) => {
1142
- const templatePath = path.join(
1143
- __dirname,
1144
- "..",
1145
- "views",
1146
- "admin-file-manager.ejs",
1147
- );
1148
- fs.readFile(templatePath, "utf8", (err, template) => {
1149
- if (err) {
1150
- console.error("Error reading template:", err);
1151
- return res.status(500).send("Error loading page");
1152
- }
1153
- try {
1154
- const html = ejs.render(
1155
- template,
1156
- {
1157
- baseUrl: req.baseUrl,
1158
- adminPath,
1159
- },
1160
- {
1161
- filename: templatePath,
1162
- },
1163
- );
1164
- res.send(html);
1165
- } catch (renderErr) {
1166
- console.error("Error rendering template:", renderErr);
1167
- res.status(500).send("Error rendering page");
1168
- }
1451
+ router.get(`${adminPath}/file-manager`, requireModuleAccessWithIframe('file-manager', 'read'), (req, res) => {
1452
+ const templatePath = path.join(
1453
+ __dirname,
1454
+ "..",
1455
+ "views",
1456
+ "admin-file-manager.ejs",
1457
+ );
1458
+ fs.readFile(templatePath, "utf8", (err, template) => {
1459
+ if (err) {
1460
+ console.error("Error reading template:", err);
1461
+ return res.status(500).send("Error loading page");
1462
+ }
1463
+ try {
1464
+ const html = ejs.render(
1465
+ template,
1466
+ {
1467
+ baseUrl: req.baseUrl,
1468
+ adminPath,
1469
+ isIframe: req.isIframe || false
1470
+ },
1471
+ {
1472
+ filename: templatePath,
1473
+ },
1474
+ );
1475
+ res.send(html);
1476
+ } catch (renderErr) {
1477
+ console.error("Error rendering template:", renderErr);
1478
+ res.status(500).send("Error rendering page");
1479
+ }
1169
1480
  });
1170
1481
  });
1171
1482
 
1172
- router.get(`${adminPath}/ejs-virtual`, basicAuth, (req, res) => {
1483
+ router.get(`${adminPath}/ejs-virtual`, requireModuleAccessWithIframe('ejs-virtual', 'read'), (req, res) => {
1173
1484
  const templatePath = path.join(
1174
1485
  __dirname,
1175
1486
  "..",
@@ -1187,6 +1498,7 @@ const telegramService = require("./services/telegram.service");
1187
1498
  {
1188
1499
  baseUrl: req.baseUrl,
1189
1500
  adminPath,
1501
+ isIframe: req.isIframe || false
1190
1502
  },
1191
1503
  {
1192
1504
  filename: templatePath,
@@ -1200,7 +1512,7 @@ const telegramService = require("./services/telegram.service");
1200
1512
  });
1201
1513
  });
1202
1514
 
1203
- router.get(`${adminPath}/seo-config`, basicAuth, (req, res) => {
1515
+ router.get(`${adminPath}/seo-config`, requireModuleAccessWithIframe('seo-config', 'read'), (req, res) => {
1204
1516
  const templatePath = path.join(
1205
1517
  __dirname,
1206
1518
  "..",
@@ -1219,6 +1531,7 @@ const telegramService = require("./services/telegram.service");
1219
1531
  baseUrl: req.baseUrl,
1220
1532
  adminPath,
1221
1533
  endpointRegistry,
1534
+ isIframe: req.isIframe || false,
1222
1535
  },
1223
1536
  {
1224
1537
  filename: templatePath,
@@ -1232,7 +1545,7 @@ const telegramService = require("./services/telegram.service");
1232
1545
  });
1233
1546
  });
1234
1547
 
1235
- router.get(`${adminPath}/i18n`, basicAuth, (req, res) => {
1548
+ router.get(`${adminPath}/i18n`, requireModuleAccessWithIframe('i18n', 'read'), (req, res) => {
1236
1549
  const templatePath = path.join(__dirname, "..", "views", "admin-i18n.ejs");
1237
1550
  fs.readFile(templatePath, "utf8", (err, template) => {
1238
1551
  if (err) {
@@ -1242,7 +1555,7 @@ const telegramService = require("./services/telegram.service");
1242
1555
  try {
1243
1556
  const html = ejs.render(
1244
1557
  template,
1245
- { baseUrl: req.baseUrl, adminPath },
1558
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1246
1559
  { filename: templatePath },
1247
1560
  );
1248
1561
  res.send(html);
@@ -1253,7 +1566,7 @@ const telegramService = require("./services/telegram.service");
1253
1566
  });
1254
1567
  });
1255
1568
 
1256
- router.get(`${adminPath}/i18n/locales`, basicAuth, (req, res) => {
1569
+ router.get(`${adminPath}/i18n/locales`, requireModuleAccessWithIframe('i18n', 'read'), (req, res) => {
1257
1570
  const templatePath = path.join(
1258
1571
  __dirname,
1259
1572
  "..",
@@ -1268,7 +1581,7 @@ const telegramService = require("./services/telegram.service");
1268
1581
  try {
1269
1582
  const html = ejs.render(
1270
1583
  template,
1271
- { baseUrl: req.baseUrl, adminPath },
1584
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1272
1585
  { filename: templatePath },
1273
1586
  );
1274
1587
  res.send(html);
@@ -1280,7 +1593,7 @@ const telegramService = require("./services/telegram.service");
1280
1593
  });
1281
1594
 
1282
1595
  // Admin forms page (protected by basic auth)
1283
- router.get(`${adminPath}/forms`, basicAuth, (req, res) => {
1596
+ router.get(`${adminPath}/forms`, requireModuleAccessWithIframe('forms', 'read'), (req, res) => {
1284
1597
  const templatePath = path.join(__dirname, "..", "views", "admin-forms.ejs");
1285
1598
  fs.readFile(templatePath, "utf8", (err, template) => {
1286
1599
  if (err) {
@@ -1294,6 +1607,7 @@ const telegramService = require("./services/telegram.service");
1294
1607
  baseUrl: req.baseUrl,
1295
1608
  adminPath,
1296
1609
  endpointRegistry,
1610
+ isIframe: req.isIframe || false
1297
1611
  },
1298
1612
  {
1299
1613
  filename: templatePath,
@@ -1308,7 +1622,7 @@ const telegramService = require("./services/telegram.service");
1308
1622
  });
1309
1623
 
1310
1624
  // Admin feature flags page (protected by basic auth)
1311
- router.get(`${adminPath}/feature-flags`, basicAuth, (req, res) => {
1625
+ router.get(`${adminPath}/feature-flags`, requireModuleAccessWithIframe('feature-flags', 'read'), (req, res) => {
1312
1626
  const templatePath = path.join(
1313
1627
  __dirname,
1314
1628
  "..",
@@ -1327,6 +1641,7 @@ const telegramService = require("./services/telegram.service");
1327
1641
  baseUrl: req.baseUrl,
1328
1642
  adminPath,
1329
1643
  endpointRegistry,
1644
+ isIframe: req.isIframe || false
1330
1645
  },
1331
1646
  {
1332
1647
  filename: templatePath,
@@ -1341,7 +1656,7 @@ const telegramService = require("./services/telegram.service");
1341
1656
  });
1342
1657
 
1343
1658
  // Admin headless CMS page (protected by basic auth)
1344
- router.get(`${adminPath}/headless`, basicAuth, (req, res) => {
1659
+ router.get(`${adminPath}/headless`, requireModuleAccessWithIframe('headless', 'read'), (req, res) => {
1345
1660
  const templatePath = path.join(
1346
1661
  __dirname,
1347
1662
  "..",
@@ -1360,6 +1675,7 @@ const telegramService = require("./services/telegram.service");
1360
1675
  baseUrl: req.baseUrl,
1361
1676
  adminPath,
1362
1677
  endpointRegistry,
1678
+ isIframe: req.isIframe || false,
1363
1679
  },
1364
1680
  {
1365
1681
  filename: templatePath,
@@ -1374,7 +1690,7 @@ const telegramService = require("./services/telegram.service");
1374
1690
  });
1375
1691
 
1376
1692
  // Admin UI Components page (protected by basic auth)
1377
- router.get(`${adminPath}/ui-components`, basicAuth, (req, res) => {
1693
+ router.get(`${adminPath}/ui-components`, requireModuleAccessWithIframe('ui-components', 'read'), (req, res) => {
1378
1694
  const templatePath = path.join(
1379
1695
  __dirname,
1380
1696
  "..",
@@ -1390,9 +1706,10 @@ const telegramService = require("./services/telegram.service");
1390
1706
  const html = ejs.render(
1391
1707
  template,
1392
1708
  {
1393
- baseUrl: req.baseUrl,
1709
+ baseUrl: req.baseUrl || '',
1394
1710
  adminPath,
1395
1711
  endpointRegistry,
1712
+ isIframe: req.isIframe || false
1396
1713
  },
1397
1714
  {
1398
1715
  filename: templatePath,
@@ -1407,7 +1724,7 @@ const telegramService = require("./services/telegram.service");
1407
1724
  });
1408
1725
 
1409
1726
  // Admin JSON configs page (protected by basic auth)
1410
- router.get(`${adminPath}/json-configs`, basicAuth, (req, res) => {
1727
+ router.get(`${adminPath}/json-configs`, requireModuleAccessWithIframe('json-configs', 'read'), (req, res) => {
1411
1728
  const templatePath = path.join(
1412
1729
  __dirname,
1413
1730
  "..",
@@ -1426,6 +1743,7 @@ const telegramService = require("./services/telegram.service");
1426
1743
  baseUrl: req.baseUrl,
1427
1744
  adminPath,
1428
1745
  endpointRegistry,
1746
+ isIframe: req.isIframe || false,
1429
1747
  },
1430
1748
  {
1431
1749
  filename: templatePath,
@@ -1440,7 +1758,7 @@ const telegramService = require("./services/telegram.service");
1440
1758
  });
1441
1759
 
1442
1760
  // Admin markdowns page (protected by basic auth)
1443
- router.get(`${adminPath}/markdowns`, basicAuth, (req, res) => {
1761
+ router.get(`${adminPath}/markdowns`, requireModuleAccessWithIframe('markdowns', 'read'), (req, res) => {
1444
1762
  const templatePath = path.join(
1445
1763
  __dirname,
1446
1764
  "..",
@@ -1459,6 +1777,7 @@ const telegramService = require("./services/telegram.service");
1459
1777
  baseUrl: req.baseUrl,
1460
1778
  adminPath,
1461
1779
  endpointRegistry,
1780
+ isIframe: req.isIframe || false,
1462
1781
  },
1463
1782
  {
1464
1783
  filename: templatePath,
@@ -1473,7 +1792,7 @@ const telegramService = require("./services/telegram.service");
1473
1792
  });
1474
1793
 
1475
1794
  // Admin assets page (protected by basic auth)
1476
- router.get(`${adminPath}/assets`, basicAuth, (req, res) => {
1795
+ router.get(`${adminPath}/assets`, requireModuleAccessWithIframe('assets', 'read'), (req, res) => {
1477
1796
  const templatePath = path.join(
1478
1797
  __dirname,
1479
1798
  "..",
@@ -1492,6 +1811,7 @@ const telegramService = require("./services/telegram.service");
1492
1811
  baseUrl: req.baseUrl,
1493
1812
  adminPath,
1494
1813
  endpointRegistry,
1814
+ isIframe: req.isIframe || false,
1495
1815
  },
1496
1816
  {
1497
1817
  filename: templatePath,
@@ -1506,7 +1826,7 @@ const telegramService = require("./services/telegram.service");
1506
1826
  });
1507
1827
 
1508
1828
  // Admin waiting list page (protected by basic auth)
1509
- router.get(`${adminPath}/waiting-list`, basicAuth, (req, res) => {
1829
+ router.get(`${adminPath}/waiting-list`, requireModuleAccessWithIframe('waiting-list', 'read'), (req, res) => {
1510
1830
  const templatePath = path.join(
1511
1831
  __dirname,
1512
1832
  "..",
@@ -1523,6 +1843,7 @@ const telegramService = require("./services/telegram.service");
1523
1843
  baseUrl: req.baseUrl,
1524
1844
  adminPath,
1525
1845
  endpointRegistry,
1846
+ isIframe: req.isIframe || false
1526
1847
  });
1527
1848
  res.send(html);
1528
1849
  } catch (renderErr) {
@@ -1533,7 +1854,7 @@ const telegramService = require("./services/telegram.service");
1533
1854
  });
1534
1855
 
1535
1856
  // Admin organizations page (protected by basic auth)
1536
- router.get(`${adminPath}/organizations`, basicAuth, (req, res) => {
1857
+ router.get(`${adminPath}/organizations`, requireModuleAccessWithIframe('organizations', 'read'), (req, res) => {
1537
1858
  const templatePath = path.join(
1538
1859
  __dirname,
1539
1860
  "..",
@@ -1552,6 +1873,7 @@ const telegramService = require("./services/telegram.service");
1552
1873
  baseUrl: req.baseUrl,
1553
1874
  adminPath,
1554
1875
  endpointRegistry,
1876
+ isIframe: req.isIframe || false
1555
1877
  },
1556
1878
  {
1557
1879
  filename: templatePath,
@@ -1565,8 +1887,8 @@ const telegramService = require("./services/telegram.service");
1565
1887
  });
1566
1888
  });
1567
1889
 
1568
- // Admin users page (protected by basic auth)
1569
- router.get(`${adminPath}/users`, basicAuth, (req, res) => {
1890
+ // Admin users page (protected by session auth)
1891
+ router.get(`${adminPath}/users`, requireModuleAccessWithIframe('users', 'read'), (req, res) => {
1570
1892
  const templatePath = path.join(__dirname, "..", "views", "admin-users.ejs");
1571
1893
  fs.readFile(templatePath, "utf8", (err, template) => {
1572
1894
  if (err) {
@@ -1577,13 +1899,11 @@ const telegramService = require("./services/telegram.service");
1577
1899
  const html = ejs.render(
1578
1900
  template,
1579
1901
  {
1580
- baseUrl: req.baseUrl,
1902
+ baseUrl: req.baseUrl,
1581
1903
  adminPath,
1582
- endpointRegistry,
1583
- },
1584
- {
1585
- filename: templatePath,
1904
+ isIframe: req.isIframe || false
1586
1905
  },
1906
+ { filename: templatePath },
1587
1907
  );
1588
1908
  res.send(html);
1589
1909
  } catch (renderErr) {
@@ -1593,8 +1913,8 @@ const telegramService = require("./services/telegram.service");
1593
1913
  });
1594
1914
  });
1595
1915
 
1596
- // Admin notifications page (protected by basic auth)
1597
- router.get(`${adminPath}/notifications`, basicAuth, (req, res) => {
1916
+ // Admin notifications page (protected by session auth)
1917
+ router.get(`${adminPath}/notifications`, requireModuleAccessWithIframe('notifications', 'read'), (req, res) => {
1598
1918
  const templatePath = path.join(
1599
1919
  __dirname,
1600
1920
  "..",
@@ -1613,6 +1933,7 @@ const telegramService = require("./services/telegram.service");
1613
1933
  baseUrl: req.baseUrl,
1614
1934
  adminPath,
1615
1935
  endpointRegistry,
1936
+ isIframe: req.isIframe || false
1616
1937
  },
1617
1938
  {
1618
1939
  filename: templatePath,
@@ -1626,8 +1947,8 @@ const telegramService = require("./services/telegram.service");
1626
1947
  });
1627
1948
  });
1628
1949
 
1629
- // Admin Stripe pricing page (protected by basic auth)
1630
- router.get(`${adminPath}/stripe-pricing`, basicAuth, (req, res) => {
1950
+ // Admin Stripe pricing page (protected by session auth)
1951
+ router.get(`${adminPath}/stripe-pricing`, adminSessionAuth, (req, res) => {
1631
1952
  const templatePath = path.join(
1632
1953
  __dirname,
1633
1954
  "..",
@@ -1654,39 +1975,38 @@ const telegramService = require("./services/telegram.service");
1654
1975
  res.send(html);
1655
1976
  } catch (renderErr) {
1656
1977
  console.error("Error rendering template:", renderErr);
1657
- res.status(500).send("Error rendering page");
1658
- }
1659
- });
1660
- });
1661
1978
 
1662
- // Admin metrics page (protected by basic auth)
1663
- router.get(`${adminPath}/metrics`, basicAuth, (req, res) => {
1664
- const templatePath = path.join(
1665
- __dirname,
1666
- "..",
1667
- "views",
1668
- "admin-metrics.ejs",
1669
- );
1670
- fs.readFile(templatePath, "utf8", (err, template) => {
1671
- if (err) {
1672
- console.error("Error reading template:", err);
1673
- return res.status(500).send("Error loading page");
1674
- }
1675
- try {
1676
- const html = ejs.render(template, {
1677
- baseUrl: req.baseUrl,
1678
- adminPath,
1679
- endpointRegistry,
1680
- });
1681
- res.send(html);
1682
- } catch (renderErr) {
1683
- console.error("Error rendering template:", renderErr);
1684
- res.status(500).send("Error rendering page");
1979
+ // Admin metrics page (protected by session auth)
1980
+ router.get(`${adminPath}/metrics`, adminSessionAuth, (req, res) => {
1981
+ const templatePath = path.join(
1982
+ __dirname,
1983
+ "..",
1984
+ "views",
1985
+ "admin-metrics.ejs",
1986
+ );
1987
+ fs.readFile(templatePath, "utf8", (err, template) => {
1988
+ if (err) {
1989
+ console.error("Error reading template:", err);
1990
+ return res.status(500).send("Error loading page");
1991
+ }
1992
+ try {
1993
+ const html = ejs.render(template, {
1994
+ baseUrl: req.baseUrl,
1995
+ adminPath,
1996
+ endpointRegistry,
1997
+ });
1998
+ res.send(html);
1999
+ } catch (renderErr) {
2000
+ console.error("Error rendering template:", renderErr);
2001
+ res.status(500).send("Error rendering page");
2002
+ }
2003
+ });
2004
+ });
1685
2005
  }
1686
2006
  });
1687
2007
  });
1688
2008
 
1689
- router.get(`${adminPath}/rate-limiter`, basicAuth, (req, res) => {
2009
+ router.get(`${adminPath}/rate-limiter`, adminSessionAuth, (req, res) => {
1690
2010
  const templatePath = path.join(
1691
2011
  __dirname,
1692
2012
  "..",
@@ -1711,8 +2031,8 @@ const telegramService = require("./services/telegram.service");
1711
2031
  });
1712
2032
  });
1713
2033
 
1714
- // Admin global settings page (protected by basic auth) - render manually
1715
- router.get(`${adminPath}/global-settings`, basicAuth, (req, res) => {
2034
+ // Admin global settings page (protected by session auth) - render manually
2035
+ router.get(`${adminPath}/global-settings`, adminSessionAuth, (req, res) => {
1716
2036
  const templatePath = path.join(
1717
2037
  __dirname,
1718
2038
  "..",
@@ -1734,7 +2054,7 @@ const telegramService = require("./services/telegram.service");
1734
2054
  });
1735
2055
  });
1736
2056
 
1737
- router.get(`${adminPath}/errors`, basicAuth, (req, res) => {
2057
+ router.get(`${adminPath}/errors`, adminSessionAuth, (req, res) => {
1738
2058
  const templatePath = path.join(
1739
2059
  __dirname,
1740
2060
  "..",
@@ -1760,7 +2080,7 @@ const telegramService = require("./services/telegram.service");
1760
2080
  });
1761
2081
  });
1762
2082
 
1763
- router.get(`${adminPath}/audit`, basicAuth, (req, res) => {
2083
+ router.get(`${adminPath}/audit`, requireModuleAccessWithIframe('audit', 'read'), (req, res) => {
1764
2084
  const templatePath = path.join(__dirname, "..", "views", "admin-audit.ejs");
1765
2085
  fs.readFile(templatePath, "utf8", (err, template) => {
1766
2086
  if (err) {
@@ -1770,7 +2090,11 @@ const telegramService = require("./services/telegram.service");
1770
2090
  try {
1771
2091
  const html = ejs.render(
1772
2092
  template,
1773
- { baseUrl: req.baseUrl, adminPath },
2093
+ {
2094
+ baseUrl: req.baseUrl,
2095
+ adminPath,
2096
+ isIframe: req.isIframe || false
2097
+ },
1774
2098
  { filename: templatePath },
1775
2099
  );
1776
2100
  res.send(html);
@@ -1781,7 +2105,7 @@ const telegramService = require("./services/telegram.service");
1781
2105
  });
1782
2106
  });
1783
2107
 
1784
- router.get(`${adminPath}/coolify-deploy`, basicAuth, (req, res) => {
2108
+ router.get(`${adminPath}/coolify-deploy`, adminSessionAuth, (req, res) => {
1785
2109
  const templatePath = path.join(
1786
2110
  __dirname,
1787
2111
  "..",
@@ -1807,7 +2131,7 @@ const telegramService = require("./services/telegram.service");
1807
2131
  });
1808
2132
  });
1809
2133
 
1810
- router.get(`${adminPath}/proxy`, basicAuth, (req, res) => {
2134
+ router.get(`${adminPath}/proxy`, adminSessionAuth, (req, res) => {
1811
2135
  const templatePath = path.join(__dirname, "..", "views", "admin-proxy.ejs");
1812
2136
  fs.readFile(templatePath, "utf8", (err, template) => {
1813
2137
  if (err) {
@@ -1828,7 +2152,7 @@ const telegramService = require("./services/telegram.service");
1828
2152
  });
1829
2153
  });
1830
2154
 
1831
- router.get(`${adminPath}/webhooks`, basicAuth, (req, res) => {
2155
+ router.get(`${adminPath}/webhooks`, adminSessionAuth, (req, res) => {
1832
2156
  const templatePath = path.join(
1833
2157
  __dirname,
1834
2158
  "..",