@intranefr/superbackend 1.5.3 → 1.6.3

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 +454 -153
  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,7 @@ const {
40
43
  requestIdMiddleware,
41
44
  } = require("./middleware/errorCapture");
42
45
  const rateLimiter = require("./services/rateLimiter.service");
46
+ const pluginsService = require("./services/plugins.service");
43
47
 
44
48
  let errorCaptureInitialized = false;
45
49
 
@@ -81,6 +85,10 @@ async function isConsoleManagerEnabled() {
81
85
  * @param {string} options.jwtSecret - JWT secret for authentication
82
86
  * @param {Object} options.dbConnection - Existing Mongoose connection
83
87
  * @param {boolean} options.skipBodyParser - Skip adding body parser middleware (default: false)
88
+ * @param {Object} options.telegram - Telegram configuration
89
+ * @param {boolean} options.telegram.enabled - Whether to enable Telegram bots (default: true)
90
+ * @param {Object} options.cron - Cron scheduler configuration
91
+ * @param {boolean} options.cron.enabled - Whether to enable cron scheduler (default: true)
84
92
  * @returns {express.Router} Configured Express router
85
93
  */
86
94
  function createMiddleware(options = {}) {
@@ -88,6 +96,66 @@ function createMiddleware(options = {}) {
88
96
  const adminPath = options.adminPath || "/admin";
89
97
  const pagesPrefix = options.pagesPrefix || "/";
90
98
 
99
+ const bootstrapPluginsRuntime = async () => {
100
+ try {
101
+ const superbackend = globalThis.superbackend || globalThis.saasbackend || {};
102
+ await pluginsService.bootstrap({
103
+ context: {
104
+ services: superbackend.services || {},
105
+ helpers: superbackend.helpers || {},
106
+ },
107
+ });
108
+ const pluginServices = pluginsService.getExposedServices();
109
+ const pluginHelpers = pluginsService.getExposedHelpers();
110
+ if (superbackend.services && typeof superbackend.services === "object") {
111
+ superbackend.services.pluginsRuntime = pluginServices;
112
+ }
113
+ if (superbackend.helpers && typeof superbackend.helpers === "object") {
114
+ superbackend.helpers.pluginsRuntime = pluginHelpers;
115
+ }
116
+ } catch (error) {
117
+ console.error("Failed to bootstrap plugins runtime:", error);
118
+ }
119
+ };
120
+
121
+ // Debug: Log received options
122
+ console.log("[Middleware Debug] Received options:", {
123
+ telegramEnabled: options.telegram?.enabled,
124
+ cronEnabled: options.cron?.enabled
125
+ });
126
+
127
+ router.get(`${adminPath}/plugins-system`, requireModuleAccessWithIframe('plugins', 'read'), (req, res) => {
128
+ const templatePath = path.join(
129
+ __dirname,
130
+ "..",
131
+ "views",
132
+ "admin-plugins-system.ejs",
133
+ );
134
+ fs.readFile(templatePath, "utf8", (err, template) => {
135
+ if (err) {
136
+ console.error("Error reading template:", err);
137
+ return res.status(500).send("Error loading page");
138
+ }
139
+ try {
140
+ const html = ejs.render(
141
+ template,
142
+ {
143
+ baseUrl: req.baseUrl,
144
+ adminPath,
145
+ isIframe: req.isIframe || false
146
+ },
147
+ {
148
+ filename: templatePath,
149
+ },
150
+ );
151
+ res.send(html);
152
+ } catch (renderErr) {
153
+ console.error("Error rendering template:", renderErr);
154
+ res.status(500).send("Error rendering page");
155
+ }
156
+ });
157
+ });
158
+
91
159
  const normalizeBasePath = (value) => {
92
160
  const v = String(value || "").trim();
93
161
  if (!v) return "/files";
@@ -168,15 +236,27 @@ const telegramService = require("./services/telegram.service");
168
236
  .connect(mongoUri, connectionOptions)
169
237
  .then(async () => {
170
238
  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
239
 
178
- // Initialize Telegram bots
179
- await telegramService.init();
240
+ // Start cron scheduler after DB connection (only if enabled)
241
+ if (options.cron?.enabled !== false) {
242
+ await cronScheduler.start();
243
+ await healthChecksScheduler.start();
244
+ await healthChecksBootstrap.bootstrap();
245
+ await blogCronsBootstrap.bootstrap();
246
+ await require("./services/experimentsCronsBootstrap.service").bootstrap();
247
+ } else {
248
+ console.log("🔍 Cron scheduler disabled - cron.enabled:", options.cron?.enabled);
249
+ }
250
+
251
+ // Initialize Telegram bots (check telegram config)
252
+ const telegramEnabled = options.telegram?.enabled !== false;
253
+ if (telegramEnabled) {
254
+ await telegramService.init();
255
+ } else {
256
+ console.log("🔍 Telegram bots disabled - telegram.enabled:", options.telegram?.enabled);
257
+ }
258
+
259
+ await bootstrapPluginsRuntime();
180
260
 
181
261
  // Console manager is already initialized early in the middleware
182
262
  console.log("[Console Manager] MongoDB connection established");
@@ -188,7 +268,7 @@ const telegramService = require("./services/telegram.service");
188
268
  return false;
189
269
  });
190
270
 
191
- router.get(`${adminPath}/health-checks`, basicAuth, (req, res) => {
271
+ router.get(`${adminPath}/health-checks`, requireModuleAccessWithIframe('health-checks', 'read'), (req, res) => {
192
272
  const templatePath = path.join(
193
273
  __dirname,
194
274
  "..",
@@ -206,6 +286,39 @@ const telegramService = require("./services/telegram.service");
206
286
  {
207
287
  baseUrl: req.baseUrl,
208
288
  adminPath,
289
+ isIframe: req.isIframe || false
290
+ },
291
+ {
292
+ filename: templatePath,
293
+ },
294
+ );
295
+ res.send(html);
296
+ } catch (renderErr) {
297
+ console.error("Error rendering template:", renderErr);
298
+ res.status(500).send("Error rendering page");
299
+ }
300
+ });
301
+ });
302
+
303
+ router.get(`${adminPath}/data-cleanup`, requireModuleAccessWithIframe('data-cleanup', 'read'), (req, res) => {
304
+ const templatePath = path.join(
305
+ __dirname,
306
+ "..",
307
+ "views",
308
+ "admin-data-cleanup.ejs",
309
+ );
310
+ fs.readFile(templatePath, "utf8", (err, template) => {
311
+ if (err) {
312
+ console.error("Error reading template:", err);
313
+ return res.status(500).send("Error loading page");
314
+ }
315
+ try {
316
+ const html = ejs.render(
317
+ template,
318
+ {
319
+ baseUrl: req.baseUrl,
320
+ adminPath,
321
+ isIframe: req.isIframe || false
209
322
  },
210
323
  {
211
324
  filename: templatePath,
@@ -219,7 +332,7 @@ const telegramService = require("./services/telegram.service");
219
332
  });
220
333
  });
221
334
 
222
- router.get(`${adminPath}/console-manager`, basicAuth, (req, res) => {
335
+ router.get(`${adminPath}/console-manager`, requireModuleAccessWithIframe('console-manager', 'read'), (req, res) => {
223
336
  const templatePath = path.join(
224
337
  __dirname,
225
338
  "..",
@@ -237,6 +350,7 @@ const telegramService = require("./services/telegram.service");
237
350
  {
238
351
  baseUrl: req.baseUrl,
239
352
  adminPath,
353
+ isIframe: req.isIframe || false
240
354
  },
241
355
  {
242
356
  filename: templatePath,
@@ -254,25 +368,44 @@ const telegramService = require("./services/telegram.service");
254
368
  router.connectionPromise = connectionPromise;
255
369
  } else if (mongoose.connection.readyState === 1) {
256
370
  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
- });
371
+
372
+ // Start cron scheduler for existing connection (only if enabled)
373
+ if (options.cron?.enabled !== false) {
374
+ cronScheduler.start().catch((err) => {
375
+ console.error("Failed to start cron scheduler:", err);
376
+ });
377
+ healthChecksScheduler.start().catch((err) => {
378
+ console.error("Failed to start health checks scheduler:", err);
379
+ });
380
+ healthChecksBootstrap.bootstrap().catch((err) => {
381
+ console.error("Failed to bootstrap health checks:", err);
382
+ });
383
+ blogCronsBootstrap.bootstrap().catch((err) => {
384
+ console.error("Failed to bootstrap blog crons:", err);
385
+ });
270
386
 
271
- require("./services/experimentsCronsBootstrap.service")
272
- .bootstrap()
273
- .catch((err) => {
274
- console.error("Failed to bootstrap experiments crons:", err);
387
+ require("./services/experimentsCronsBootstrap.service")
388
+ .bootstrap()
389
+ .catch((err) => {
390
+ console.error("Failed to bootstrap experiments crons:", err);
391
+ });
392
+ } else {
393
+ console.log("🔍 Cron scheduler disabled - cron.enabled:", options.cron?.enabled, "(existing connection)");
394
+ }
395
+
396
+ // Initialize Telegram bots for existing connection (check telegram config)
397
+ const telegramEnabled = options.telegram?.enabled !== false;
398
+ if (telegramEnabled) {
399
+ telegramService.init().catch(err => {
400
+ console.error("Failed to initialize Telegram service (existing connection):", err);
275
401
  });
402
+ } else {
403
+ console.log("🔍 Telegram bots disabled - telegram.enabled:", options.telegram?.enabled, "(existing connection)");
404
+ }
405
+
406
+ bootstrapPluginsRuntime().catch((err) => {
407
+ console.error("Failed to bootstrap plugins runtime (existing connection):", err);
408
+ });
276
409
 
277
410
  // Initialize console manager AFTER database is already connected
278
411
  if (process.env.NODE_ENV !== "test" && !process.env.JEST_WORKER_ID) {
@@ -367,10 +500,34 @@ const telegramService = require("./services/telegram.service");
367
500
  router.use(express.urlencoded({ extended: true }));
368
501
  }
369
502
 
503
+ // Session middleware for admin authentication
504
+ const sessionMiddleware = session({
505
+ secret: process.env.SESSION_SECRET || 'superbackend-session-secret-fallback',
506
+ resave: false,
507
+ saveUninitialized: false,
508
+ cookie: {
509
+ secure: process.env.NODE_ENV === 'production',
510
+ httpOnly: true,
511
+ maxAge: 24 * 60 * 60 * 1000, // 24 hours
512
+ sameSite: 'lax'
513
+ },
514
+ store: MongoStore.create({
515
+ mongoUrl: options.mongodbUri || process.env.MONGODB_URI,
516
+ collectionName: 'admin_sessions',
517
+ ttl: 24 * 60 * 60 // 24 hours in seconds
518
+ }),
519
+ name: 'superbackend.admin.session'
520
+ });
521
+
522
+ router.use(sessionMiddleware);
523
+
370
524
  router.use(requestIdMiddleware);
371
525
 
372
526
  router.use("/api", rateLimiter.limit("globalApiLimiter"));
373
527
 
528
+ // Serve public static files with /public prefix (for admin UI components)
529
+ router.use("/public", express.static(path.join(__dirname, "..", "public")));
530
+
374
531
  // Serve public static files (e.g. /og/og-default.png)
375
532
  router.use(express.static(path.join(__dirname, "..", "public")));
376
533
 
@@ -448,7 +605,7 @@ const telegramService = require("./services/telegram.service");
448
605
  require("./routes/waitingListAdmin.routes"),
449
606
  );
450
607
  router.use("/api/admin/orgs", require("./routes/orgAdmin.routes"));
451
- router.use("/api/admin/users", require("./routes/userAdmin.routes"));
608
+ router.use("/api/admin/users", requireModuleAccessWithIframe('users', 'read'), require("./routes/userAdmin.routes"));
452
609
  router.use("/api/admin/rbac", require("./routes/adminRbac.routes"));
453
610
  router.use(
454
611
  "/api/admin/notifications",
@@ -460,11 +617,111 @@ const telegramService = require("./services/telegram.service");
460
617
  const adminStatsController = require("./controllers/adminStats.controller");
461
618
  router.get(
462
619
  "/api/admin/stats/overview",
463
- basicAuth,
620
+ adminSessionAuth,
464
621
  adminStatsController.getOverviewStats,
465
622
  );
466
623
 
467
- router.get(`${adminPath}/stats/dashboard-home`, basicAuth, (req, res) => {
624
+ // Middleware to check if request is from authenticated parent iframe
625
+ function checkIframeAuth(req, res, next) {
626
+ const referer = req.get('Referer');
627
+ const origin = req.get('Origin');
628
+ const adminPath = req.adminPath || '/admin';
629
+
630
+ // Check for iframe token parameter (more reliable than referer)
631
+ const iframeToken = req.query.iframe_token;
632
+ if (iframeToken && iframeToken === 'authenticated') {
633
+ req.isIframe = true;
634
+ return next();
635
+ }
636
+
637
+ // Fallback to referer/origin check
638
+ const isValidReferer = referer && referer.includes(adminPath);
639
+ const isValidOrigin = origin && origin.includes(req.hostname);
640
+
641
+ if (isValidReferer || isValidOrigin) {
642
+ req.isIframe = true;
643
+ return next();
644
+ }
645
+
646
+ // If not from iframe, require normal authentication
647
+ return adminSessionAuth(req, res, next);
648
+ }
649
+
650
+ // Combined middleware for iframe authentication + module access
651
+ function requireModuleAccessWithIframe(moduleId, action = 'read') {
652
+ return async (req, res, next) => {
653
+ try {
654
+ // Check for iframe authentication first
655
+ const referer = req.get('Referer');
656
+ const origin = req.get('Origin');
657
+ const adminPath = req.adminPath || '/admin';
658
+ const iframeToken = req.query.iframe_token;
659
+
660
+ const isValidIframe = (iframeToken && iframeToken === 'authenticated') ||
661
+ (referer && referer.includes(adminPath)) ||
662
+ (origin && origin.includes(req.hostname));
663
+
664
+ if (isValidIframe) {
665
+ req.isIframe = true;
666
+ // For iframe requests, we'll allow access but mark it as iframe context
667
+ return next();
668
+ }
669
+
670
+ // Check for basic auth superadmin bypass
671
+ if (isBasicAuthSuperAdmin(req)) {
672
+ return next();
673
+ }
674
+
675
+ // Get user ID from session
676
+ const userId = req.session?.authData?.userId;
677
+ if (!userId) {
678
+ return res.redirect(`${req.adminPath || '/admin'}/login`);
679
+ }
680
+
681
+ // Check RBAC permission for specific module
682
+ const hasAccess = await rbacService.checkRight({
683
+ userId,
684
+ orgId: null, // Global admin permissions
685
+ right: `admin_panel__${moduleId}:${action}`
686
+ });
687
+
688
+ if (!hasAccess.allowed) {
689
+ // For API routes, return JSON error
690
+ if (req.path.startsWith('/api/')) {
691
+ return res.status(403).json({
692
+ error: 'Access denied',
693
+ reason: hasAccess.reason,
694
+ required: `admin_panel__${moduleId}:${action}`,
695
+ moduleId,
696
+ action
697
+ });
698
+ }
699
+
700
+ // For page routes, render 403 page
701
+ return res.status(403).render('admin-403', {
702
+ moduleId,
703
+ action,
704
+ required: `admin_panel__${moduleId}:${action}`,
705
+ reason: hasAccess.reason,
706
+ user: req.session.authData,
707
+ adminPath: req.adminPath || '/admin'
708
+ });
709
+ }
710
+
711
+ next();
712
+ } catch (error) {
713
+ console.error('Module access check error:', error);
714
+
715
+ if (req.path.startsWith('/api/')) {
716
+ return res.status(500).json({ error: 'Access check failed' });
717
+ } else {
718
+ return res.status(500).send('Access check failed');
719
+ }
720
+ }
721
+ };
722
+ }
723
+
724
+ router.get(`${adminPath}/stats/dashboard-home`, checkIframeAuth, (req, res) => {
468
725
  const templatePath = path.join(
469
726
  __dirname,
470
727
  "..",
@@ -479,7 +736,11 @@ const telegramService = require("./services/telegram.service");
479
736
  try {
480
737
  const html = ejs.render(
481
738
  template,
482
- { baseUrl: req.baseUrl, adminPath },
739
+ {
740
+ baseUrl: req.baseUrl,
741
+ adminPath,
742
+ isIframe: req.isIframe || false
743
+ },
483
744
  { filename: templatePath },
484
745
  );
485
746
  res.send(html);
@@ -490,7 +751,7 @@ const telegramService = require("./services/telegram.service");
490
751
  });
491
752
  });
492
753
 
493
- router.get(`${adminPath}/experiments`, basicAuth, (req, res) => {
754
+ router.get(`${adminPath}/experiments`, requireModuleAccessWithIframe('experiments', 'read'), (req, res) => {
494
755
  const templatePath = path.join(
495
756
  __dirname,
496
757
  "..",
@@ -508,6 +769,7 @@ const telegramService = require("./services/telegram.service");
508
769
  {
509
770
  baseUrl: req.baseUrl,
510
771
  adminPath,
772
+ isIframe: req.isIframe || false
511
773
  },
512
774
  {
513
775
  filename: templatePath,
@@ -521,7 +783,7 @@ const telegramService = require("./services/telegram.service");
521
783
  });
522
784
  });
523
785
 
524
- router.get(`${adminPath}/rbac`, basicAuth, (req, res) => {
786
+ router.get(`${adminPath}/rbac`, requireModuleAccessWithIframe('rbac', 'read'), (req, res) => {
525
787
  const templatePath = path.join(__dirname, "..", "views", "admin-rbac.ejs");
526
788
  fs.readFile(templatePath, "utf8", (err, template) => {
527
789
  if (err) {
@@ -534,6 +796,7 @@ const telegramService = require("./services/telegram.service");
534
796
  {
535
797
  baseUrl: req.baseUrl,
536
798
  adminPath,
799
+ isIframe: req.isIframe || false
537
800
  },
538
801
  {
539
802
  filename: templatePath,
@@ -547,7 +810,7 @@ const telegramService = require("./services/telegram.service");
547
810
  });
548
811
  });
549
812
 
550
- router.get(`${adminPath}/terminals`, basicAuth, (req, res) => {
813
+ router.get(`${adminPath}/terminals`, requireModuleAccessWithIframe('terminals', 'read'), (req, res) => {
551
814
  const templatePath = path.join(
552
815
  __dirname,
553
816
  "..",
@@ -566,6 +829,7 @@ const telegramService = require("./services/telegram.service");
566
829
  baseUrl: req.baseUrl,
567
830
  adminPath,
568
831
  endpointRegistry,
832
+ isIframe: req.isIframe || false
569
833
  },
570
834
  {
571
835
  filename: templatePath,
@@ -579,7 +843,7 @@ const telegramService = require("./services/telegram.service");
579
843
  });
580
844
  });
581
845
 
582
- router.get(`${adminPath}/scripts`, basicAuth, (req, res) => {
846
+ router.get(`${adminPath}/scripts`, requireModuleAccessWithIframe('scripts', 'read'), (req, res) => {
583
847
  const templatePath = path.join(
584
848
  __dirname,
585
849
  "..",
@@ -598,6 +862,7 @@ const telegramService = require("./services/telegram.service");
598
862
  baseUrl: req.baseUrl,
599
863
  adminPath,
600
864
  endpointRegistry,
865
+ isIframe: req.isIframe || false
601
866
  },
602
867
  {
603
868
  filename: templatePath,
@@ -611,7 +876,7 @@ const telegramService = require("./services/telegram.service");
611
876
  });
612
877
  });
613
878
 
614
- router.get(`${adminPath}/crons`, basicAuth, (req, res) => {
879
+ router.get(`${adminPath}/crons`, requireModuleAccessWithIframe('crons', 'read'), (req, res) => {
615
880
  const templatePath = path.join(__dirname, "..", "views", "admin-crons.ejs");
616
881
  fs.readFile(templatePath, "utf8", (err, template) => {
617
882
  if (err) {
@@ -624,6 +889,7 @@ const telegramService = require("./services/telegram.service");
624
889
  {
625
890
  baseUrl: req.baseUrl,
626
891
  adminPath,
892
+ isIframe: req.isIframe || false
627
893
  },
628
894
  {
629
895
  filename: templatePath,
@@ -637,7 +903,7 @@ const telegramService = require("./services/telegram.service");
637
903
  });
638
904
  });
639
905
 
640
- router.get(`${adminPath}/cache`, basicAuth, (req, res) => {
906
+ router.get(`${adminPath}/cache`, requireModuleAccessWithIframe('cache', 'read'), (req, res) => {
641
907
  const templatePath = path.join(__dirname, "..", "views", "admin-cache.ejs");
642
908
  fs.readFile(templatePath, "utf8", (err, template) => {
643
909
  if (err) {
@@ -650,6 +916,7 @@ const telegramService = require("./services/telegram.service");
650
916
  {
651
917
  baseUrl: req.baseUrl,
652
918
  adminPath,
919
+ isIframe: req.isIframe || false
653
920
  },
654
921
  {
655
922
  filename: templatePath,
@@ -663,7 +930,7 @@ const telegramService = require("./services/telegram.service");
663
930
  });
664
931
  });
665
932
 
666
- router.get(`${adminPath}/db-browser`, basicAuth, (req, res) => {
933
+ router.get(`${adminPath}/db-browser`, requireModuleAccessWithIframe('db-browser', 'read'), (req, res) => {
667
934
  const templatePath = path.join(
668
935
  __dirname,
669
936
  "..",
@@ -681,6 +948,7 @@ const telegramService = require("./services/telegram.service");
681
948
  {
682
949
  baseUrl: req.baseUrl,
683
950
  adminPath,
951
+ isIframe: req.isIframe || false
684
952
  },
685
953
  {
686
954
  filename: templatePath,
@@ -694,7 +962,7 @@ const telegramService = require("./services/telegram.service");
694
962
  });
695
963
  });
696
964
 
697
- router.get(`${adminPath}/telegram`, basicAuth, (req, res) => {
965
+ router.get(`${adminPath}/telegram`, requireModuleAccessWithIframe('telegram', 'read'), (req, res) => {
698
966
  const templatePath = path.join(
699
967
  __dirname,
700
968
  "..",
@@ -712,6 +980,7 @@ const telegramService = require("./services/telegram.service");
712
980
  {
713
981
  baseUrl: req.baseUrl,
714
982
  adminPath,
983
+ isIframe: req.isIframe || false
715
984
  },
716
985
  {
717
986
  filename: templatePath,
@@ -725,7 +994,7 @@ const telegramService = require("./services/telegram.service");
725
994
  });
726
995
  });
727
996
 
728
- router.get(`${adminPath}/agents`, basicAuth, (req, res) => {
997
+ router.get(`${adminPath}/agents`, requireModuleAccessWithIframe('agents', 'read'), (req, res) => {
729
998
  const templatePath = path.join(
730
999
  __dirname,
731
1000
  "..",
@@ -743,6 +1012,7 @@ const telegramService = require("./services/telegram.service");
743
1012
  {
744
1013
  baseUrl: req.baseUrl,
745
1014
  adminPath,
1015
+ isIframe: req.isIframe || false
746
1016
  },
747
1017
  {
748
1018
  filename: templatePath,
@@ -796,6 +1066,10 @@ const telegramService = require("./services/telegram.service");
796
1066
  "/api/admin/db-browser",
797
1067
  require("./routes/adminDbBrowser.routes"),
798
1068
  );
1069
+ router.use(
1070
+ "/api/admin/data-cleanup",
1071
+ require("./routes/adminDataCleanup.routes"),
1072
+ );
799
1073
  router.use("/api/admin/terminals", require("./routes/adminTerminals.routes"));
800
1074
  router.use("/api/admin/experiments", require("./routes/adminExperiments.routes"));
801
1075
  router.use("/api/admin/assets", require("./routes/adminAssets.routes"));
@@ -810,17 +1084,19 @@ const telegramService = require("./services/telegram.service");
810
1084
  router.use("/api/admin/migration", require("./routes/adminMigration.routes"));
811
1085
  router.use(
812
1086
  "/api/admin/errors",
813
- basicAuth,
1087
+ adminSessionAuth,
814
1088
  require("./routes/adminErrors.routes"),
815
1089
  );
816
1090
  router.use(
817
1091
  "/api/admin/audit",
818
- basicAuth,
1092
+ requireModuleAccessWithIframe('audit', 'read'),
819
1093
  require("./routes/adminAudit.routes"),
820
1094
  );
821
1095
  router.use("/api/admin/llm", require("./routes/adminLlm.routes"));
822
1096
  router.use("/api/admin/telegram", require("./routes/adminTelegram.routes"));
823
1097
  router.use("/api/admin/agents", require("./routes/adminAgents.routes"));
1098
+ router.use("/api/admin/registries", require("./routes/adminRegistry.routes"));
1099
+ router.use("/api/admin/plugins", require("./routes/adminPlugins.routes"));
824
1100
  router.use(
825
1101
  "/api/admin/ejs-virtual",
826
1102
  require("./routes/adminEjsVirtual.routes"),
@@ -829,7 +1105,7 @@ const telegramService = require("./services/telegram.service");
829
1105
  router.use("/api/admin", require("./routes/adminBlog.routes"));
830
1106
  router.use("/api/admin", require("./routes/adminBlogAi.routes"));
831
1107
  router.use("/api/admin", require("./routes/adminBlogAutomation.routes"));
832
- router.use("/api/admin/workflows", basicAuth, require("./routes/workflows.routes"));
1108
+ router.use("/api/admin/workflows", adminSessionAuth, require("./routes/workflows.routes"));
833
1109
  router.use("/w", require("./routes/workflowWebhook.routes"));
834
1110
  router.use("/api/webhooks", require("./routes/webhook.routes"));
835
1111
  router.use("/api/settings", require("./routes/globalSettings.routes"));
@@ -847,6 +1123,7 @@ const telegramService = require("./services/telegram.service");
847
1123
  router.use("/api/error-tracking", require("./routes/errorTracking.routes"));
848
1124
  router.use("/api/ui-components", require("./routes/uiComponentsPublic.routes"));
849
1125
  router.use("/api/rbac", require("./routes/rbac.routes"));
1126
+ router.use("/registry", require("./routes/registry.routes"));
850
1127
  router.use("/api/file-manager", require("./routes/fileManager.routes"));
851
1128
  router.use("/api/experiments", require("./routes/experiments.routes"));
852
1129
 
@@ -868,8 +1145,14 @@ const telegramService = require("./services/telegram.service");
868
1145
  // Public assets proxy
869
1146
  router.use("/public/assets", require("./routes/publicAssets.routes"));
870
1147
 
871
- // Admin dashboard (polished view)
872
- router.get(adminPath, basicAuth, (req, res) => {
1148
+ // Admin login routes (no authentication required)
1149
+ router.use(`${adminPath}`, (req, res, next) => {
1150
+ req.adminPath = adminPath;
1151
+ next();
1152
+ }, require("./routes/adminLogin.routes"));
1153
+
1154
+ // Admin dashboard (redirect to login if not authenticated)
1155
+ router.get(adminPath, adminSessionAuth, (req, res) => {
873
1156
  const templatePath = path.join(
874
1157
  __dirname,
875
1158
  "..",
@@ -884,7 +1167,7 @@ const telegramService = require("./services/telegram.service");
884
1167
  try {
885
1168
  const html = ejs.render(
886
1169
  template,
887
- { baseUrl: req.baseUrl, adminPath },
1170
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
888
1171
  { filename: templatePath },
889
1172
  );
890
1173
  res.send(html);
@@ -895,8 +1178,8 @@ const telegramService = require("./services/telegram.service");
895
1178
  });
896
1179
  });
897
1180
 
898
- // Admin technical API test page (protected by basic auth)
899
- router.get(`${adminPath}/api/test`, basicAuth, (req, res) => {
1181
+ // Admin technical API test page (protected by session auth)
1182
+ router.get(`${adminPath}/api/test`, adminSessionAuth, (req, res) => {
900
1183
  const templatePath = path.join(__dirname, "..", "views", "admin-test.ejs");
901
1184
  fs.readFile(templatePath, "utf8", (err, template) => {
902
1185
  if (err) {
@@ -910,6 +1193,7 @@ const telegramService = require("./services/telegram.service");
910
1193
  baseUrl: req.baseUrl,
911
1194
  adminPath,
912
1195
  endpointRegistry,
1196
+ isIframe: req.isIframe || false,
913
1197
  },
914
1198
  {
915
1199
  filename: templatePath,
@@ -923,7 +1207,7 @@ const telegramService = require("./services/telegram.service");
923
1207
  });
924
1208
  });
925
1209
 
926
- router.get(`${adminPath}/migration`, basicAuth, (req, res) => {
1210
+ router.get(`${adminPath}/migration`, requireModuleAccessWithIframe('migration', 'read'), (req, res) => {
927
1211
  const templatePath = path.join(
928
1212
  __dirname,
929
1213
  "..",
@@ -941,7 +1225,7 @@ const telegramService = require("./services/telegram.service");
941
1225
  {
942
1226
  baseUrl: req.baseUrl,
943
1227
  adminPath,
944
- endpointRegistry,
1228
+ isIframe: req.isIframe || false
945
1229
  },
946
1230
  {
947
1231
  filename: templatePath,
@@ -956,7 +1240,7 @@ const telegramService = require("./services/telegram.service");
956
1240
  });
957
1241
 
958
1242
  // Admin LLM/AI page (protected by basic auth)
959
- router.get(`${adminPath}/admin-llm`, basicAuth, (req, res) => {
1243
+ router.get(`${adminPath}/admin-llm`, requireModuleAccessWithIframe('admin-llm', 'read'), (req, res) => {
960
1244
  const templatePath = path.join(__dirname, "..", "views", "admin-llm.ejs");
961
1245
  fs.readFile(templatePath, "utf8", (err, template) => {
962
1246
  if (err) {
@@ -969,6 +1253,7 @@ const telegramService = require("./services/telegram.service");
969
1253
  {
970
1254
  baseUrl: req.baseUrl,
971
1255
  adminPath,
1256
+ isIframe: req.isIframe || false
972
1257
  },
973
1258
  {
974
1259
  filename: templatePath,
@@ -982,7 +1267,7 @@ const telegramService = require("./services/telegram.service");
982
1267
  });
983
1268
  });
984
1269
 
985
- router.get(`${adminPath}/workflows/:id`, basicAuth, (req, res) => {
1270
+ router.get(`${adminPath}/workflows/:id`, adminSessionAuth, (req, res) => {
986
1271
  const templatePath = path.join(
987
1272
  __dirname,
988
1273
  "..",
@@ -997,7 +1282,7 @@ const telegramService = require("./services/telegram.service");
997
1282
  try {
998
1283
  const html = ejs.render(
999
1284
  template,
1000
- { baseUrl: req.baseUrl, adminPath },
1285
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1001
1286
  { filename: templatePath },
1002
1287
  );
1003
1288
  res.send(html);
@@ -1008,7 +1293,7 @@ const telegramService = require("./services/telegram.service");
1008
1293
  });
1009
1294
  });
1010
1295
 
1011
- router.get(`${adminPath}/pages`, basicAuth, (req, res) => {
1296
+ router.get(`${adminPath}/pages`, requireModuleAccessWithIframe('pages', 'read'), (req, res) => {
1012
1297
  const templatePath = path.join(__dirname, "..", "views", "admin-pages.ejs");
1013
1298
  fs.readFile(templatePath, "utf8", (err, template) => {
1014
1299
  if (err) {
@@ -1021,6 +1306,7 @@ const telegramService = require("./services/telegram.service");
1021
1306
  {
1022
1307
  baseUrl: req.baseUrl,
1023
1308
  adminPath,
1309
+ isIframe: req.isIframe || false
1024
1310
  },
1025
1311
  {
1026
1312
  filename: templatePath,
@@ -1034,7 +1320,7 @@ const telegramService = require("./services/telegram.service");
1034
1320
  });
1035
1321
  });
1036
1322
 
1037
- router.get(`${adminPath}/blog`, basicAuth, (req, res) => {
1323
+ router.get(`${adminPath}/blog`, requireModuleAccessWithIframe('blog', 'read'), (req, res) => {
1038
1324
  const templatePath = path.join(__dirname, "..", "views", "admin-blog.ejs");
1039
1325
  fs.readFile(templatePath, "utf8", (err, template) => {
1040
1326
  if (err) {
@@ -1044,7 +1330,7 @@ const telegramService = require("./services/telegram.service");
1044
1330
  try {
1045
1331
  const html = ejs.render(
1046
1332
  template,
1047
- { baseUrl: req.baseUrl, adminPath },
1333
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1048
1334
  { filename: templatePath },
1049
1335
  );
1050
1336
  res.send(html);
@@ -1055,7 +1341,7 @@ const telegramService = require("./services/telegram.service");
1055
1341
  });
1056
1342
  });
1057
1343
 
1058
- router.get(`${adminPath}/blog-automation`, basicAuth, (req, res) => {
1344
+ router.get(`${adminPath}/blog-automation`, requireModuleAccessWithIframe('blog-automation', 'read'), (req, res) => {
1059
1345
  const templatePath = path.join(
1060
1346
  __dirname,
1061
1347
  "..",
@@ -1070,7 +1356,7 @@ const telegramService = require("./services/telegram.service");
1070
1356
  try {
1071
1357
  const html = ejs.render(
1072
1358
  template,
1073
- { baseUrl: req.baseUrl, adminPath },
1359
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1074
1360
  { filename: templatePath },
1075
1361
  );
1076
1362
  res.send(html);
@@ -1081,7 +1367,7 @@ const telegramService = require("./services/telegram.service");
1081
1367
  });
1082
1368
  });
1083
1369
 
1084
- router.get(`${adminPath}/blog/new`, basicAuth, (req, res) => {
1370
+ router.get(`${adminPath}/blog/new`, requireModuleAccessWithIframe('blog', 'read'), (req, res) => {
1085
1371
  const templatePath = path.join(
1086
1372
  __dirname,
1087
1373
  "..",
@@ -1096,7 +1382,7 @@ const telegramService = require("./services/telegram.service");
1096
1382
  try {
1097
1383
  const html = ejs.render(
1098
1384
  template,
1099
- { baseUrl: req.baseUrl, adminPath, postId: "", mode: "new" },
1385
+ { baseUrl: req.baseUrl, adminPath, postId: "", mode: "new", isIframe: req.isIframe || false },
1100
1386
  { filename: templatePath },
1101
1387
  );
1102
1388
  res.send(html);
@@ -1107,7 +1393,7 @@ const telegramService = require("./services/telegram.service");
1107
1393
  });
1108
1394
  });
1109
1395
 
1110
- router.get(`${adminPath}/blog/edit/:id`, basicAuth, (req, res) => {
1396
+ router.get(`${adminPath}/blog/edit/:id`, requireModuleAccessWithIframe('blog', 'read'), (req, res) => {
1111
1397
  const templatePath = path.join(
1112
1398
  __dirname,
1113
1399
  "..",
@@ -1127,6 +1413,7 @@ const telegramService = require("./services/telegram.service");
1127
1413
  adminPath,
1128
1414
  postId: String(req.params.id || ""),
1129
1415
  mode: "edit",
1416
+ isIframe: req.isIframe || false,
1130
1417
  },
1131
1418
  { filename: templatePath },
1132
1419
  );
@@ -1138,38 +1425,39 @@ const telegramService = require("./services/telegram.service");
1138
1425
  });
1139
1426
  });
1140
1427
 
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
- }
1428
+ router.get(`${adminPath}/file-manager`, requireModuleAccessWithIframe('file-manager', 'read'), (req, res) => {
1429
+ const templatePath = path.join(
1430
+ __dirname,
1431
+ "..",
1432
+ "views",
1433
+ "admin-file-manager.ejs",
1434
+ );
1435
+ fs.readFile(templatePath, "utf8", (err, template) => {
1436
+ if (err) {
1437
+ console.error("Error reading template:", err);
1438
+ return res.status(500).send("Error loading page");
1439
+ }
1440
+ try {
1441
+ const html = ejs.render(
1442
+ template,
1443
+ {
1444
+ baseUrl: req.baseUrl,
1445
+ adminPath,
1446
+ isIframe: req.isIframe || false
1447
+ },
1448
+ {
1449
+ filename: templatePath,
1450
+ },
1451
+ );
1452
+ res.send(html);
1453
+ } catch (renderErr) {
1454
+ console.error("Error rendering template:", renderErr);
1455
+ res.status(500).send("Error rendering page");
1456
+ }
1169
1457
  });
1170
1458
  });
1171
1459
 
1172
- router.get(`${adminPath}/ejs-virtual`, basicAuth, (req, res) => {
1460
+ router.get(`${adminPath}/ejs-virtual`, requireModuleAccessWithIframe('ejs-virtual', 'read'), (req, res) => {
1173
1461
  const templatePath = path.join(
1174
1462
  __dirname,
1175
1463
  "..",
@@ -1187,6 +1475,7 @@ const telegramService = require("./services/telegram.service");
1187
1475
  {
1188
1476
  baseUrl: req.baseUrl,
1189
1477
  adminPath,
1478
+ isIframe: req.isIframe || false
1190
1479
  },
1191
1480
  {
1192
1481
  filename: templatePath,
@@ -1200,7 +1489,7 @@ const telegramService = require("./services/telegram.service");
1200
1489
  });
1201
1490
  });
1202
1491
 
1203
- router.get(`${adminPath}/seo-config`, basicAuth, (req, res) => {
1492
+ router.get(`${adminPath}/seo-config`, requireModuleAccessWithIframe('seo-config', 'read'), (req, res) => {
1204
1493
  const templatePath = path.join(
1205
1494
  __dirname,
1206
1495
  "..",
@@ -1219,6 +1508,7 @@ const telegramService = require("./services/telegram.service");
1219
1508
  baseUrl: req.baseUrl,
1220
1509
  adminPath,
1221
1510
  endpointRegistry,
1511
+ isIframe: req.isIframe || false,
1222
1512
  },
1223
1513
  {
1224
1514
  filename: templatePath,
@@ -1232,7 +1522,7 @@ const telegramService = require("./services/telegram.service");
1232
1522
  });
1233
1523
  });
1234
1524
 
1235
- router.get(`${adminPath}/i18n`, basicAuth, (req, res) => {
1525
+ router.get(`${adminPath}/i18n`, requireModuleAccessWithIframe('i18n', 'read'), (req, res) => {
1236
1526
  const templatePath = path.join(__dirname, "..", "views", "admin-i18n.ejs");
1237
1527
  fs.readFile(templatePath, "utf8", (err, template) => {
1238
1528
  if (err) {
@@ -1242,7 +1532,7 @@ const telegramService = require("./services/telegram.service");
1242
1532
  try {
1243
1533
  const html = ejs.render(
1244
1534
  template,
1245
- { baseUrl: req.baseUrl, adminPath },
1535
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1246
1536
  { filename: templatePath },
1247
1537
  );
1248
1538
  res.send(html);
@@ -1253,7 +1543,7 @@ const telegramService = require("./services/telegram.service");
1253
1543
  });
1254
1544
  });
1255
1545
 
1256
- router.get(`${adminPath}/i18n/locales`, basicAuth, (req, res) => {
1546
+ router.get(`${adminPath}/i18n/locales`, requireModuleAccessWithIframe('i18n', 'read'), (req, res) => {
1257
1547
  const templatePath = path.join(
1258
1548
  __dirname,
1259
1549
  "..",
@@ -1268,7 +1558,7 @@ const telegramService = require("./services/telegram.service");
1268
1558
  try {
1269
1559
  const html = ejs.render(
1270
1560
  template,
1271
- { baseUrl: req.baseUrl, adminPath },
1561
+ { baseUrl: req.baseUrl, adminPath, isIframe: req.isIframe || false },
1272
1562
  { filename: templatePath },
1273
1563
  );
1274
1564
  res.send(html);
@@ -1280,7 +1570,7 @@ const telegramService = require("./services/telegram.service");
1280
1570
  });
1281
1571
 
1282
1572
  // Admin forms page (protected by basic auth)
1283
- router.get(`${adminPath}/forms`, basicAuth, (req, res) => {
1573
+ router.get(`${adminPath}/forms`, requireModuleAccessWithIframe('forms', 'read'), (req, res) => {
1284
1574
  const templatePath = path.join(__dirname, "..", "views", "admin-forms.ejs");
1285
1575
  fs.readFile(templatePath, "utf8", (err, template) => {
1286
1576
  if (err) {
@@ -1294,6 +1584,7 @@ const telegramService = require("./services/telegram.service");
1294
1584
  baseUrl: req.baseUrl,
1295
1585
  adminPath,
1296
1586
  endpointRegistry,
1587
+ isIframe: req.isIframe || false
1297
1588
  },
1298
1589
  {
1299
1590
  filename: templatePath,
@@ -1308,7 +1599,7 @@ const telegramService = require("./services/telegram.service");
1308
1599
  });
1309
1600
 
1310
1601
  // Admin feature flags page (protected by basic auth)
1311
- router.get(`${adminPath}/feature-flags`, basicAuth, (req, res) => {
1602
+ router.get(`${adminPath}/feature-flags`, requireModuleAccessWithIframe('feature-flags', 'read'), (req, res) => {
1312
1603
  const templatePath = path.join(
1313
1604
  __dirname,
1314
1605
  "..",
@@ -1327,6 +1618,7 @@ const telegramService = require("./services/telegram.service");
1327
1618
  baseUrl: req.baseUrl,
1328
1619
  adminPath,
1329
1620
  endpointRegistry,
1621
+ isIframe: req.isIframe || false
1330
1622
  },
1331
1623
  {
1332
1624
  filename: templatePath,
@@ -1341,7 +1633,7 @@ const telegramService = require("./services/telegram.service");
1341
1633
  });
1342
1634
 
1343
1635
  // Admin headless CMS page (protected by basic auth)
1344
- router.get(`${adminPath}/headless`, basicAuth, (req, res) => {
1636
+ router.get(`${adminPath}/headless`, requireModuleAccessWithIframe('headless', 'read'), (req, res) => {
1345
1637
  const templatePath = path.join(
1346
1638
  __dirname,
1347
1639
  "..",
@@ -1360,6 +1652,7 @@ const telegramService = require("./services/telegram.service");
1360
1652
  baseUrl: req.baseUrl,
1361
1653
  adminPath,
1362
1654
  endpointRegistry,
1655
+ isIframe: req.isIframe || false,
1363
1656
  },
1364
1657
  {
1365
1658
  filename: templatePath,
@@ -1374,7 +1667,7 @@ const telegramService = require("./services/telegram.service");
1374
1667
  });
1375
1668
 
1376
1669
  // Admin UI Components page (protected by basic auth)
1377
- router.get(`${adminPath}/ui-components`, basicAuth, (req, res) => {
1670
+ router.get(`${adminPath}/ui-components`, requireModuleAccessWithIframe('ui-components', 'read'), (req, res) => {
1378
1671
  const templatePath = path.join(
1379
1672
  __dirname,
1380
1673
  "..",
@@ -1390,9 +1683,10 @@ const telegramService = require("./services/telegram.service");
1390
1683
  const html = ejs.render(
1391
1684
  template,
1392
1685
  {
1393
- baseUrl: req.baseUrl,
1686
+ baseUrl: req.baseUrl || '',
1394
1687
  adminPath,
1395
1688
  endpointRegistry,
1689
+ isIframe: req.isIframe || false
1396
1690
  },
1397
1691
  {
1398
1692
  filename: templatePath,
@@ -1407,7 +1701,7 @@ const telegramService = require("./services/telegram.service");
1407
1701
  });
1408
1702
 
1409
1703
  // Admin JSON configs page (protected by basic auth)
1410
- router.get(`${adminPath}/json-configs`, basicAuth, (req, res) => {
1704
+ router.get(`${adminPath}/json-configs`, requireModuleAccessWithIframe('json-configs', 'read'), (req, res) => {
1411
1705
  const templatePath = path.join(
1412
1706
  __dirname,
1413
1707
  "..",
@@ -1426,6 +1720,7 @@ const telegramService = require("./services/telegram.service");
1426
1720
  baseUrl: req.baseUrl,
1427
1721
  adminPath,
1428
1722
  endpointRegistry,
1723
+ isIframe: req.isIframe || false,
1429
1724
  },
1430
1725
  {
1431
1726
  filename: templatePath,
@@ -1440,7 +1735,7 @@ const telegramService = require("./services/telegram.service");
1440
1735
  });
1441
1736
 
1442
1737
  // Admin markdowns page (protected by basic auth)
1443
- router.get(`${adminPath}/markdowns`, basicAuth, (req, res) => {
1738
+ router.get(`${adminPath}/markdowns`, requireModuleAccessWithIframe('markdowns', 'read'), (req, res) => {
1444
1739
  const templatePath = path.join(
1445
1740
  __dirname,
1446
1741
  "..",
@@ -1459,6 +1754,7 @@ const telegramService = require("./services/telegram.service");
1459
1754
  baseUrl: req.baseUrl,
1460
1755
  adminPath,
1461
1756
  endpointRegistry,
1757
+ isIframe: req.isIframe || false,
1462
1758
  },
1463
1759
  {
1464
1760
  filename: templatePath,
@@ -1473,7 +1769,7 @@ const telegramService = require("./services/telegram.service");
1473
1769
  });
1474
1770
 
1475
1771
  // Admin assets page (protected by basic auth)
1476
- router.get(`${adminPath}/assets`, basicAuth, (req, res) => {
1772
+ router.get(`${adminPath}/assets`, requireModuleAccessWithIframe('assets', 'read'), (req, res) => {
1477
1773
  const templatePath = path.join(
1478
1774
  __dirname,
1479
1775
  "..",
@@ -1492,6 +1788,7 @@ const telegramService = require("./services/telegram.service");
1492
1788
  baseUrl: req.baseUrl,
1493
1789
  adminPath,
1494
1790
  endpointRegistry,
1791
+ isIframe: req.isIframe || false,
1495
1792
  },
1496
1793
  {
1497
1794
  filename: templatePath,
@@ -1506,7 +1803,7 @@ const telegramService = require("./services/telegram.service");
1506
1803
  });
1507
1804
 
1508
1805
  // Admin waiting list page (protected by basic auth)
1509
- router.get(`${adminPath}/waiting-list`, basicAuth, (req, res) => {
1806
+ router.get(`${adminPath}/waiting-list`, requireModuleAccessWithIframe('waiting-list', 'read'), (req, res) => {
1510
1807
  const templatePath = path.join(
1511
1808
  __dirname,
1512
1809
  "..",
@@ -1523,6 +1820,7 @@ const telegramService = require("./services/telegram.service");
1523
1820
  baseUrl: req.baseUrl,
1524
1821
  adminPath,
1525
1822
  endpointRegistry,
1823
+ isIframe: req.isIframe || false
1526
1824
  });
1527
1825
  res.send(html);
1528
1826
  } catch (renderErr) {
@@ -1533,7 +1831,7 @@ const telegramService = require("./services/telegram.service");
1533
1831
  });
1534
1832
 
1535
1833
  // Admin organizations page (protected by basic auth)
1536
- router.get(`${adminPath}/organizations`, basicAuth, (req, res) => {
1834
+ router.get(`${adminPath}/organizations`, requireModuleAccessWithIframe('organizations', 'read'), (req, res) => {
1537
1835
  const templatePath = path.join(
1538
1836
  __dirname,
1539
1837
  "..",
@@ -1552,6 +1850,7 @@ const telegramService = require("./services/telegram.service");
1552
1850
  baseUrl: req.baseUrl,
1553
1851
  adminPath,
1554
1852
  endpointRegistry,
1853
+ isIframe: req.isIframe || false
1555
1854
  },
1556
1855
  {
1557
1856
  filename: templatePath,
@@ -1565,8 +1864,8 @@ const telegramService = require("./services/telegram.service");
1565
1864
  });
1566
1865
  });
1567
1866
 
1568
- // Admin users page (protected by basic auth)
1569
- router.get(`${adminPath}/users`, basicAuth, (req, res) => {
1867
+ // Admin users page (protected by session auth)
1868
+ router.get(`${adminPath}/users`, requireModuleAccessWithIframe('users', 'read'), (req, res) => {
1570
1869
  const templatePath = path.join(__dirname, "..", "views", "admin-users.ejs");
1571
1870
  fs.readFile(templatePath, "utf8", (err, template) => {
1572
1871
  if (err) {
@@ -1577,13 +1876,11 @@ const telegramService = require("./services/telegram.service");
1577
1876
  const html = ejs.render(
1578
1877
  template,
1579
1878
  {
1580
- baseUrl: req.baseUrl,
1879
+ baseUrl: req.baseUrl,
1581
1880
  adminPath,
1582
- endpointRegistry,
1583
- },
1584
- {
1585
- filename: templatePath,
1881
+ isIframe: req.isIframe || false
1586
1882
  },
1883
+ { filename: templatePath },
1587
1884
  );
1588
1885
  res.send(html);
1589
1886
  } catch (renderErr) {
@@ -1593,8 +1890,8 @@ const telegramService = require("./services/telegram.service");
1593
1890
  });
1594
1891
  });
1595
1892
 
1596
- // Admin notifications page (protected by basic auth)
1597
- router.get(`${adminPath}/notifications`, basicAuth, (req, res) => {
1893
+ // Admin notifications page (protected by session auth)
1894
+ router.get(`${adminPath}/notifications`, requireModuleAccessWithIframe('notifications', 'read'), (req, res) => {
1598
1895
  const templatePath = path.join(
1599
1896
  __dirname,
1600
1897
  "..",
@@ -1613,6 +1910,7 @@ const telegramService = require("./services/telegram.service");
1613
1910
  baseUrl: req.baseUrl,
1614
1911
  adminPath,
1615
1912
  endpointRegistry,
1913
+ isIframe: req.isIframe || false
1616
1914
  },
1617
1915
  {
1618
1916
  filename: templatePath,
@@ -1626,8 +1924,8 @@ const telegramService = require("./services/telegram.service");
1626
1924
  });
1627
1925
  });
1628
1926
 
1629
- // Admin Stripe pricing page (protected by basic auth)
1630
- router.get(`${adminPath}/stripe-pricing`, basicAuth, (req, res) => {
1927
+ // Admin Stripe pricing page (protected by session auth)
1928
+ router.get(`${adminPath}/stripe-pricing`, adminSessionAuth, (req, res) => {
1631
1929
  const templatePath = path.join(
1632
1930
  __dirname,
1633
1931
  "..",
@@ -1654,39 +1952,38 @@ const telegramService = require("./services/telegram.service");
1654
1952
  res.send(html);
1655
1953
  } catch (renderErr) {
1656
1954
  console.error("Error rendering template:", renderErr);
1657
- res.status(500).send("Error rendering page");
1658
- }
1659
- });
1660
- });
1661
1955
 
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");
1956
+ // Admin metrics page (protected by session auth)
1957
+ router.get(`${adminPath}/metrics`, adminSessionAuth, (req, res) => {
1958
+ const templatePath = path.join(
1959
+ __dirname,
1960
+ "..",
1961
+ "views",
1962
+ "admin-metrics.ejs",
1963
+ );
1964
+ fs.readFile(templatePath, "utf8", (err, template) => {
1965
+ if (err) {
1966
+ console.error("Error reading template:", err);
1967
+ return res.status(500).send("Error loading page");
1968
+ }
1969
+ try {
1970
+ const html = ejs.render(template, {
1971
+ baseUrl: req.baseUrl,
1972
+ adminPath,
1973
+ endpointRegistry,
1974
+ });
1975
+ res.send(html);
1976
+ } catch (renderErr) {
1977
+ console.error("Error rendering template:", renderErr);
1978
+ res.status(500).send("Error rendering page");
1979
+ }
1980
+ });
1981
+ });
1685
1982
  }
1686
1983
  });
1687
1984
  });
1688
1985
 
1689
- router.get(`${adminPath}/rate-limiter`, basicAuth, (req, res) => {
1986
+ router.get(`${adminPath}/rate-limiter`, adminSessionAuth, (req, res) => {
1690
1987
  const templatePath = path.join(
1691
1988
  __dirname,
1692
1989
  "..",
@@ -1711,8 +2008,8 @@ const telegramService = require("./services/telegram.service");
1711
2008
  });
1712
2009
  });
1713
2010
 
1714
- // Admin global settings page (protected by basic auth) - render manually
1715
- router.get(`${adminPath}/global-settings`, basicAuth, (req, res) => {
2011
+ // Admin global settings page (protected by session auth) - render manually
2012
+ router.get(`${adminPath}/global-settings`, adminSessionAuth, (req, res) => {
1716
2013
  const templatePath = path.join(
1717
2014
  __dirname,
1718
2015
  "..",
@@ -1734,7 +2031,7 @@ const telegramService = require("./services/telegram.service");
1734
2031
  });
1735
2032
  });
1736
2033
 
1737
- router.get(`${adminPath}/errors`, basicAuth, (req, res) => {
2034
+ router.get(`${adminPath}/errors`, adminSessionAuth, (req, res) => {
1738
2035
  const templatePath = path.join(
1739
2036
  __dirname,
1740
2037
  "..",
@@ -1760,7 +2057,7 @@ const telegramService = require("./services/telegram.service");
1760
2057
  });
1761
2058
  });
1762
2059
 
1763
- router.get(`${adminPath}/audit`, basicAuth, (req, res) => {
2060
+ router.get(`${adminPath}/audit`, requireModuleAccessWithIframe('audit', 'read'), (req, res) => {
1764
2061
  const templatePath = path.join(__dirname, "..", "views", "admin-audit.ejs");
1765
2062
  fs.readFile(templatePath, "utf8", (err, template) => {
1766
2063
  if (err) {
@@ -1770,7 +2067,11 @@ const telegramService = require("./services/telegram.service");
1770
2067
  try {
1771
2068
  const html = ejs.render(
1772
2069
  template,
1773
- { baseUrl: req.baseUrl, adminPath },
2070
+ {
2071
+ baseUrl: req.baseUrl,
2072
+ adminPath,
2073
+ isIframe: req.isIframe || false
2074
+ },
1774
2075
  { filename: templatePath },
1775
2076
  );
1776
2077
  res.send(html);
@@ -1781,7 +2082,7 @@ const telegramService = require("./services/telegram.service");
1781
2082
  });
1782
2083
  });
1783
2084
 
1784
- router.get(`${adminPath}/coolify-deploy`, basicAuth, (req, res) => {
2085
+ router.get(`${adminPath}/coolify-deploy`, adminSessionAuth, (req, res) => {
1785
2086
  const templatePath = path.join(
1786
2087
  __dirname,
1787
2088
  "..",
@@ -1807,7 +2108,7 @@ const telegramService = require("./services/telegram.service");
1807
2108
  });
1808
2109
  });
1809
2110
 
1810
- router.get(`${adminPath}/proxy`, basicAuth, (req, res) => {
2111
+ router.get(`${adminPath}/proxy`, adminSessionAuth, (req, res) => {
1811
2112
  const templatePath = path.join(__dirname, "..", "views", "admin-proxy.ejs");
1812
2113
  fs.readFile(templatePath, "utf8", (err, template) => {
1813
2114
  if (err) {
@@ -1828,7 +2129,7 @@ const telegramService = require("./services/telegram.service");
1828
2129
  });
1829
2130
  });
1830
2131
 
1831
- router.get(`${adminPath}/webhooks`, basicAuth, (req, res) => {
2132
+ router.get(`${adminPath}/webhooks`, adminSessionAuth, (req, res) => {
1832
2133
  const templatePath = path.join(
1833
2134
  __dirname,
1834
2135
  "..",