mbkbucket 3.5.1 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.env.example +14 -14
  2. package/.mbkbucket.config.example.json +14 -14
  3. package/LICENSE +20 -20
  4. package/README.md +377 -350
  5. package/index.js +30 -30
  6. package/lib/cli.js +5 -4
  7. package/lib/public/bucketadmin.css +1695 -1420
  8. package/lib/public/bucketadmin.js +1229 -1229
  9. package/lib/public/mbkbucket-helper-demo.html +1184 -1184
  10. package/lib/public/mbkbucket-helper.css +1235 -1235
  11. package/lib/public/mbkbucket-helper.js +1557 -1557
  12. package/lib/src/app.js +109 -109
  13. package/lib/src/cli/auth-helper.js +141 -150
  14. package/lib/src/config/index.js +110 -112
  15. package/lib/src/config/validation.js +73 -73
  16. package/lib/src/controllers/api.controller.js +410 -410
  17. package/lib/src/controllers/dashboard.controller.js +49 -48
  18. package/lib/src/controllers/info.controller.js +33 -34
  19. package/lib/src/controllers/view.controller.js +231 -233
  20. package/lib/src/middleware/async-handler.js +19 -23
  21. package/lib/src/middleware/bucket-resolver.js +37 -37
  22. package/lib/src/middleware/error-handler.js +50 -54
  23. package/lib/src/middleware/rate-limiter.js +22 -22
  24. package/lib/src/middleware/security.js +21 -27
  25. package/lib/src/routes/api.routes.js +53 -40
  26. package/lib/src/routes/index.js +60 -21
  27. package/lib/src/routes/info.routes.js +9 -9
  28. package/lib/src/routes/view.routes.js +25 -20
  29. package/lib/src/services/s3.service.js +594 -603
  30. package/lib/src/utils/errors.js +46 -54
  31. package/lib/src/utils/helpers.js +212 -251
  32. package/lib/src/utils/logger.js +17 -17
  33. package/package.json +83 -83
  34. package/views/bucket.handlebars +196 -196
  35. package/views/bucketadmin_alerts.handlebars +15 -15
  36. package/views/bucketadmin_delete_modal.handlebars +36 -36
  37. package/views/bucketadmin_filelist_skeleton.handlebars +32 -32
  38. package/views/bucketadmin_newfolder_modal.handlebars +29 -29
  39. package/views/bucketadmin_preview_modal.handlebars +40 -40
  40. package/views/bucketadmin_upload_modal.handlebars +54 -54
  41. package/views/bucketadmincontent.handlebars +141 -141
  42. package/views/mbkbucket_info.handlebars +232 -232
@@ -1,23 +1,19 @@
1
- /**
2
- * Wraps an async Express route handler so that any thrown/rejected errors
3
- * are forwarded to `next(err)` instead of crashing the process.
4
- */
5
- export function wrap(handler, onError) {
6
- return (req, res, next) => {
7
- Promise.resolve(handler(req, res, next)).catch(err => (onError ? onError(err, req, res, next) : next(err)));
8
- };
9
- }
10
-
11
- /**
12
- * Combines wrap() with a standard JSON error response for API routes.
13
- */
14
- export function wrapApi(handler, fallbackMessage = 'Request failed') {
15
- return wrap(handler, (err, _req, res) => {
16
- console.error(`[mbkbucket] ${err.stack || err.message}`);
17
- res.status(500).json({
18
- success: false,
19
- code: 'INTERNAL_ERROR',
20
- error: err.message || fallbackMessage,
21
- });
22
- });
23
- }
1
+ /**
2
+ * Wraps an async Express route handler so that any thrown/rejected errors
3
+ * are forwarded to `next(err)` instead of crashing the process.
4
+ */
5
+ export const wrap = (handler, onError) => (req, res, next) =>
6
+ Promise.resolve(handler(req, res, next)).catch(err => onError ? onError(err, req, res, next) : next(err));
7
+
8
+ /**
9
+ * Combines wrap() with a standard JSON error response for API routes.
10
+ */
11
+ export const wrapApi = (handler, fallbackMessage = 'Request failed') =>
12
+ wrap(handler, (err, _req, res) => {
13
+ console.error(`[mbkbucket] ${err.stack || err.message}`);
14
+ res.status(500).json({
15
+ success: false,
16
+ code: 'INTERNAL_ERROR',
17
+ error: err.message || fallbackMessage,
18
+ });
19
+ });
@@ -1,37 +1,37 @@
1
- import { resolveBucketName } from "../services/s3.service.js";
2
- import { sendApiError, sendViewError } from "../utils/errors.js";
3
-
4
- const NO_BUCKET_MSG = 'No bucket selected. Provide ?bucket=<name> or configure a default bucket in mbkautheVar.bucket.';
5
-
6
- /**
7
- * Resolves `?bucket=<name>` query param and attaches `req.activeBucket` and `req.bucketResolveError`.
8
- */
9
- export function bucketResolver(req, _res, next) {
10
- try {
11
- req.activeBucket = resolveBucketName(req.query.bucket);
12
- req.bucketResolveError = null;
13
- } catch (err) {
14
- req.activeBucket = null;
15
- req.bucketResolveError = err;
16
- }
17
- next();
18
- }
19
-
20
- /**
21
- * Guard middleware for API routes — returns 400/503 JSON if bucket is invalid.
22
- */
23
- export function requireBucketApi(req, res, next) {
24
- if (req.bucketResolveError) return sendApiError(res, req.bucketResolveError, 'Invalid bucket selection');
25
- if (!req.activeBucket) return sendApiError(res, new Error(NO_BUCKET_MSG));
26
- next();
27
- }
28
-
29
- /**
30
- * Guard middleware for view routes — returns 400/503 JSON if bucket is invalid (skips /p_view/...).
31
- */
32
- export function requireBucketView(req, res, next) {
33
- if (req.path.startsWith('/p_view/')) return next();
34
- if (req.bucketResolveError) return sendViewError(res, req.bucketResolveError, 'Invalid bucket selection');
35
- if (!req.activeBucket) return sendViewError(res, new Error(NO_BUCKET_MSG));
36
- next();
37
- }
1
+ import { resolveBucketName } from "../services/s3.service.js";
2
+ import { sendApiError, sendViewError } from "../utils/errors.js";
3
+
4
+ const NO_BUCKET_MSG = 'No bucket selected. Provide ?bucket=<name> or configure a default bucket in mbkautheVar.bucket.';
5
+
6
+ /**
7
+ * Resolves `?bucket=<name>` query param and attaches `req.activeBucket` and `req.bucketResolveError`.
8
+ */
9
+ export function bucketResolver(req, _res, next) {
10
+ try {
11
+ req.activeBucket = resolveBucketName(req.query.bucket);
12
+ req.bucketResolveError = null;
13
+ } catch (err) {
14
+ req.activeBucket = null;
15
+ req.bucketResolveError = err;
16
+ }
17
+ next();
18
+ }
19
+
20
+ /**
21
+ * Guard middleware for API routes — returns 400/503 JSON if bucket is invalid.
22
+ */
23
+ export function requireBucketApi(req, res, next) {
24
+ if (req.bucketResolveError) return sendApiError(res, req.bucketResolveError, 'Invalid bucket selection');
25
+ if (!req.activeBucket) return sendApiError(res, new Error(NO_BUCKET_MSG));
26
+ next();
27
+ }
28
+
29
+ /**
30
+ * Guard middleware for view routes — returns 400/503 JSON if bucket is invalid (skips /p_view/...).
31
+ */
32
+ export function requireBucketView(req, res, next) {
33
+ if (req.path.startsWith('/p_view/')) return next();
34
+ if (req.bucketResolveError) return sendViewError(res, req.bucketResolveError, 'Invalid bucket selection');
35
+ if (!req.activeBucket) return sendViewError(res, new Error(NO_BUCKET_MSG));
36
+ next();
37
+ }
@@ -1,54 +1,50 @@
1
- import { createLogger } from "#logger";
2
- import { isJsonRequest, sendError, sanitizeErrorDetails } from "mbkauthe";
3
-
4
- const debugServer = createLogger('server');
5
-
6
- const BASE_ERROR_DATA = { layout: false, pagename: "Home", page: "/" };
7
-
8
- export function notFoundHandler(req, res, next) {
9
- const url = req.originalUrl || req.url || '';
10
- if (!url.startsWith('/mbkbucket') && typeof next === 'function') {
11
- return next();
12
- }
13
-
14
- debugServer("Path not found: %s %s", req.method, req.url);
15
-
16
- if (isJsonRequest(req)) {
17
- return sendError(res, "The requested API route was not found.", {
18
- statusCode: 404,
19
- code: "ROUTE_NOT_FOUND",
20
- req,
21
- });
22
- }
23
-
24
- return res.status(404).render("Error/dError.handlebars", {
25
- ...BASE_ERROR_DATA,
26
- code: 404,
27
- error: "Not Found",
28
- message: "The requested page was not found.",
29
- });
30
- }
31
-
32
- export function globalErrorHandler(err, req, res, _next) {
33
- console.error(`[mbkbucket] ${err.stack || err}`);
34
-
35
- const statusCode = Number(err.status || err.statusCode || 500);
36
-
37
- if (isJsonRequest(req)) {
38
- return sendError(res, err, {
39
- statusCode,
40
- req,
41
- details: process.env.NODE_ENV !== 'production' ? err.stack : undefined,
42
- });
43
- }
44
-
45
- const sanitizedDetails = err.message ? sanitizeErrorDetails(err.message) : undefined;
46
-
47
- return res.status(statusCode).render("Error/dError.handlebars", {
48
- ...BASE_ERROR_DATA,
49
- code: statusCode,
50
- error: statusCode >= 500 ? "Internal app Error" : (err.name || "Client Error"),
51
- message: err.message || "An unexpected error occurred on the app.",
52
- ...(sanitizedDetails ? { details: sanitizedDetails } : {}),
53
- });
54
- }
1
+ import { createLogger } from "#logger";
2
+ import { isJsonRequest, sendError, sanitizeErrorDetails } from "mbkauthe";
3
+
4
+ const debugServer = createLogger('server');
5
+ const BASE_ERROR_DATA = { layout: false, pagename: "Home", page: "/" };
6
+
7
+ export function notFoundHandler(req, res, next) {
8
+ const url = req.originalUrl || req.url || '';
9
+ if (!url.startsWith('/mbkbucket') && typeof next === 'function') return next();
10
+
11
+ debugServer("Path not found: %s %s", req.method, req.url);
12
+
13
+ if (isJsonRequest(req)) {
14
+ return sendError(res, "The requested API route was not found.", {
15
+ statusCode: 404,
16
+ code: "ROUTE_NOT_FOUND",
17
+ req,
18
+ });
19
+ }
20
+
21
+ return res.status(404).render("Error/dError.handlebars", {
22
+ ...BASE_ERROR_DATA,
23
+ code: 404,
24
+ error: "Not Found",
25
+ message: "The requested page was not found.",
26
+ });
27
+ }
28
+
29
+ export function globalErrorHandler(err, req, res, _next) {
30
+ console.error(`[mbkbucket] ${err.stack || err}`);
31
+ const statusCode = Number(err.status || err.statusCode || 500);
32
+
33
+ if (isJsonRequest(req)) {
34
+ return sendError(res, err, {
35
+ statusCode,
36
+ req,
37
+ details: process.env.NODE_ENV !== 'production' ? err.stack : undefined,
38
+ });
39
+ }
40
+
41
+ const sanitizedDetails = err.message ? sanitizeErrorDetails(err.message) : undefined;
42
+
43
+ return res.status(statusCode).render("Error/dError.handlebars", {
44
+ ...BASE_ERROR_DATA,
45
+ code: statusCode,
46
+ error: statusCode >= 500 ? "Internal app Error" : (err.name || "Client Error"),
47
+ message: err.message || "An unexpected error occurred on the app.",
48
+ ...(sanitizedDetails && { details: sanitizedDetails }),
49
+ });
50
+ }
@@ -1,22 +1,22 @@
1
- import rateLimit from "express-rate-limit";
2
-
3
- export const generalLimiter = rateLimit({
4
- windowMs: 2 * 60 * 1000, // 2 minutes
5
- max: 150,
6
- standardHeaders: true,
7
- legacyHeaders: false,
8
- handler: (_req, res) => {
9
- res.status(429).render('error.handlebars', { message: 'Too many requests from your IP. Try again later.', code: 429 });
10
- }
11
- });
12
-
13
- export const pviewRateLimit = rateLimit({
14
- windowMs: 60 * 1000, // 1 minute
15
- max: 10,
16
- standardHeaders: 'draft-7',
17
- legacyHeaders: false,
18
- keyGenerator: req => req.headers['x-forwarded-for']?.split(',')[0].trim() || req.socket.remoteAddress || 'unknown',
19
- handler: (_req, res) => {
20
- res.status(429).json({ message: 'Too many requests. Please slow down and try again later.' });
21
- }
22
- });
1
+ import rateLimit from "express-rate-limit";
2
+
3
+ export const generalLimiter = rateLimit({
4
+ windowMs: 2 * 60 * 1000,
5
+ max: 150,
6
+ standardHeaders: true,
7
+ legacyHeaders: false,
8
+ handler: (_req, res) => {
9
+ res.status(429).render('error.handlebars', { message: 'Too many requests from your IP. Try again later.', code: 429 });
10
+ }
11
+ });
12
+
13
+ export const pviewRateLimit = rateLimit({
14
+ windowMs: 60 * 1000,
15
+ max: 10,
16
+ standardHeaders: 'draft-7',
17
+ legacyHeaders: false,
18
+ keyGenerator: req => req.headers['x-forwarded-for']?.split(',')[0].trim() || req.socket.remoteAddress || 'unknown',
19
+ handler: (_req, res) => {
20
+ res.status(429).json({ message: 'Too many requests. Please slow down and try again later.' });
21
+ }
22
+ });
@@ -1,27 +1,21 @@
1
- /**
2
- * Security middleware for public view (p_view) routes.
3
- * Blocks bot/scraper User-Agents and sets security headers.
4
- */
5
-
6
- const BLOCKED_UA_PATTERNS = /curl|wget|python-requests|python-urllib|go-http|scrapy|libwww|java\/|bot|crawl|spider|headless|phantom|selenium|puppeteer|playwright|postman|insomnia|httpie/i;
7
-
8
- const SUSPICIOUS_HEADERS = [
9
- 'x-devtools-emulate-network-conditions-client-id',
10
- 'x-chromedriver-clientid',
11
- 'x-automated-tool'
12
- ];
13
-
14
- export function pviewSecurity(req, res, next) {
15
- const ua = req.headers['user-agent'] || '';
16
-
17
- if (!ua || BLOCKED_UA_PATTERNS.test(ua) || !req.headers.accept || SUSPICIOUS_HEADERS.some(h => h in req.headers)) {
18
- return res.status(403).json({ message: 'Forbidden' });
19
- }
20
-
21
- res.setHeader('X-Content-Type-Options', 'nosniff');
22
- res.setHeader('X-Frame-Options', 'SAMEORIGIN');
23
- res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
24
- res.removeHeader('Access-Control-Allow-Origin');
25
-
26
- next();
27
- }
1
+ /**
2
+ * Security middleware for public view (p_view) routes.
3
+ * Blocks bot/scraper User-Agents and sets security headers.
4
+ */
5
+
6
+ const BLOCKED_UA_PATTERNS = /curl|wget|python-requests|python-urllib|go-http|scrapy|libwww|java\/|bot|crawl|spider|headless|phantom|selenium|puppeteer|playwright|postman|insomnia|httpie/i;
7
+ const SUSPICIOUS_HEADERS = ['x-devtools-emulate-network-conditions-client-id', 'x-chromedriver-clientid', 'x-automated-tool'];
8
+
9
+ export function pviewSecurity(req, res, next) {
10
+ const ua = req.headers['user-agent'] || '';
11
+
12
+ if (!ua || BLOCKED_UA_PATTERNS.test(ua) || !req.headers.accept || SUSPICIOUS_HEADERS.some(h => h in req.headers)) {
13
+ return res.status(403).json({ message: 'Forbidden' });
14
+ }
15
+
16
+ res.setHeader('X-Content-Type-Options', 'nosniff');
17
+ res.setHeader('X-Frame-Options', 'SAMEORIGIN');
18
+ res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
19
+ res.removeHeader('Access-Control-Allow-Origin');
20
+ next();
21
+ }
@@ -1,40 +1,53 @@
1
- import express from "express";
2
- import { sessRole } from "mbkauthe";
3
- import multer from "multer";
4
- import { requireBucketApi } from "../middleware/bucket-resolver.js";
5
- import { cleanupUploads, listIncompleteUploads, listFiles, uploadSingleFile, initiateMultipartUpload, uploadChunk, completeUpload, abortUpload, createFolder, deleteItems, downloadFileHandler } from "../controllers/api.controller.js";
6
-
7
- const router = express.Router();
8
- const MAX_CHUNK_SIZE = 50 * 1024 * 1024; // 50 MB
9
- const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: MAX_CHUNK_SIZE } });
10
-
11
- const uploadChunkMiddleware = (req, res, next) => {
12
- upload.single('chunk')(req, res, (err) => {
13
- if (err?.code === 'LIMIT_FILE_SIZE') {
14
- return res.status(413).json({
15
- success: false,
16
- error: `Chunk too large (max ${Math.round(MAX_CHUNK_SIZE / (1024 * 1024))} MB).`,
17
- });
18
- }
19
- if (err) return next(err);
20
- next();
21
- });
22
- };
23
-
24
- const adminAuth = sessRole('superadmin');
25
-
26
- router.use(requireBucketApi);
27
-
28
- router.post('/api/cleanup-uploads', adminAuth, cleanupUploads);
29
- router.get('/api/incomplete-uploads', adminAuth, listIncompleteUploads);
30
- router.get('/api/files', adminAuth, listFiles);
31
- router.post('/upload', adminAuth, upload.single('file'), uploadSingleFile);
32
- router.post('/upload-init', adminAuth, initiateMultipartUpload);
33
- router.post('/upload-chunk', adminAuth, uploadChunkMiddleware, uploadChunk);
34
- router.post('/upload-complete', adminAuth, completeUpload);
35
- router.post('/upload-abort', adminAuth, abortUpload);
36
- router.post('/create-folder', adminAuth, createFolder);
37
- router.post('/delete', adminAuth, deleteItems);
38
- router.get('/download/*key', adminAuth, downloadFileHandler);
39
-
40
- export default router;
1
+ import express from "express";
2
+ import { sessRole } from "mbkauthe";
3
+ import multer from "multer";
4
+ import { requireBucketApi } from "../middleware/bucket-resolver.js";
5
+ import { cleanupUploads, listIncompleteUploads, listFiles, uploadSingleFile, initiateMultipartUpload, uploadChunk, completeUpload, abortUpload, createFolder, deleteItems, downloadFileHandler } from "../controllers/api.controller.js";
6
+
7
+ const MAX_CHUNK_SIZE = 50 * 1024 * 1024; // 50 MB
8
+ const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: MAX_CHUNK_SIZE } });
9
+
10
+ const uploadChunkMiddleware = (req, res, next) => {
11
+ upload.single('chunk')(req, res, (err) => {
12
+ if (err?.code === 'LIMIT_FILE_SIZE') {
13
+ return res.status(413).json({
14
+ success: false,
15
+ error: `Chunk too large (max ${Math.round(MAX_CHUNK_SIZE / (1024 * 1024))} MB).`,
16
+ });
17
+ }
18
+ if (err) return next(err);
19
+ next();
20
+ });
21
+ };
22
+
23
+ export function createApiRoutes({
24
+ authorization,
25
+ viewAuthorization,
26
+ uploadAuthorization,
27
+ deleteAuthorization,
28
+ } = {}) {
29
+ const apiRouter = express.Router();
30
+ const defaultAuth = authorization ?? sessRole('superadmin');
31
+ const viewAuth = viewAuthorization ?? defaultAuth;
32
+ const uploadAuth = uploadAuthorization ?? defaultAuth;
33
+ const deleteAuth = deleteAuthorization ?? defaultAuth;
34
+
35
+ apiRouter.use(requireBucketApi);
36
+ apiRouter.post('/api/cleanup-uploads', deleteAuth, cleanupUploads);
37
+ apiRouter.get('/api/incomplete-uploads', viewAuth, listIncompleteUploads);
38
+ apiRouter.get('/api/files', viewAuth, listFiles);
39
+ apiRouter.post('/upload', uploadAuth, upload.single('file'), uploadSingleFile);
40
+ apiRouter.post('/upload-init', uploadAuth, initiateMultipartUpload);
41
+ apiRouter.post('/upload-chunk', uploadAuth, uploadChunkMiddleware, uploadChunk);
42
+ apiRouter.post('/upload-complete', uploadAuth, completeUpload);
43
+ apiRouter.post('/upload-abort', deleteAuth, abortUpload);
44
+ apiRouter.post('/create-folder', uploadAuth, createFolder);
45
+ apiRouter.post('/delete', deleteAuth, deleteItems);
46
+ apiRouter.get('/download/*key', viewAuth, downloadFileHandler);
47
+
48
+ return apiRouter;
49
+ }
50
+
51
+ const router = createApiRoutes();
52
+
53
+ export default router;
@@ -1,21 +1,60 @@
1
- /**
2
- * MBKBucket
3
- * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
4
- * Licensed under the MIT License.
5
- * Source: https://github.com/MIbnEKhalid/mbkbucket
6
- */
7
-
8
- import express from "express";
9
- import { sessRole } from "mbkauthe";
10
- import { bucketResolver } from "../middleware/bucket-resolver.js";
11
- import { renderBucketDashboard } from "../controllers/dashboard.controller.js";
12
- import infoRoutes from "./info.routes.js";
13
- import viewRoutes from "./view.routes.js";
14
- import apiRoutes from "./api.routes.js";
15
-
16
- const router = express.Router();
17
-
18
- router.get('/mbkbucket', sessRole('superadmin'), renderBucketDashboard);
19
- router.use('/mbkbucket', bucketResolver, infoRoutes, viewRoutes, apiRoutes);
20
-
21
- export default router;
1
+ /**
2
+ * MBKBucket
3
+ * Copyright (c) 2026 Muhammad Bin Khalid, MBKTech.org and contributors
4
+ * Licensed under the MIT License.
5
+ * Source: https://github.com/MIbnEKhalid/mbkbucket
6
+ */
7
+
8
+ import express from "express";
9
+ import { sessRole } from "mbkauthe";
10
+ import path from "path";
11
+ import { fileURLToPath } from "url";
12
+ import { bucketResolver } from "../middleware/bucket-resolver.js";
13
+ import { renderBucketDashboard } from "../controllers/dashboard.controller.js";
14
+ import infoRoutes from "./info.routes.js";
15
+ import { createViewRoutes } from "./view.routes.js";
16
+ import { createApiRoutes } from "./api.routes.js";
17
+
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+ const publicDir = path.resolve(__dirname, "..", "..", "public");
21
+
22
+ const serveAsset = (filename) => (_req, res) => {
23
+ res.set("Cache-Control", "public, max-age=300, must-revalidate");
24
+ res.sendFile(path.join(publicDir, filename), (err) => {
25
+ if (err) res.status(err.status || 404).end();
26
+ });
27
+ };
28
+
29
+ export function createBucketRouter({ authorization } = {}) {
30
+ const router = express.Router();
31
+ const defaultAuth = sessRole('superadmin');
32
+ const auths = typeof authorization === 'function'
33
+ ? { view: authorization, upload: authorization, delete: authorization }
34
+ : authorization ?? {};
35
+ const viewAuth = auths.view ?? defaultAuth;
36
+ const uploadAuth = auths.upload ?? defaultAuth;
37
+ const deleteAuth = auths.delete ?? defaultAuth;
38
+
39
+ // Static dashboard & helper assets
40
+ router.get('/mbkbucket/bucketadmin.css', serveAsset('bucketadmin.css'));
41
+ router.get('/mbkbucket/bucketadmin.js', serveAsset('bucketadmin.js'));
42
+ router.get('/mbkbucket/mbkbucket-helper.css', serveAsset('mbkbucket-helper.css'));
43
+ router.get('/mbkbucket/mbkbucket-helper.js', serveAsset('mbkbucket-helper.js'));
44
+ router.get('/mbkbucket/helper-demo', serveAsset('mbkbucket-helper-demo.html'));
45
+
46
+ router.get('/mbkbucket', viewAuth, renderBucketDashboard);
47
+ router.use(
48
+ '/mbkbucket',
49
+ bucketResolver,
50
+ infoRoutes,
51
+ createViewRoutes({ authorization: viewAuth }),
52
+ createApiRoutes({ viewAuthorization: viewAuth, uploadAuthorization: uploadAuth, deleteAuthorization: deleteAuth })
53
+ );
54
+
55
+ return router;
56
+ }
57
+
58
+ const router = createBucketRouter();
59
+
60
+ export default router;
@@ -1,9 +1,9 @@
1
- import express from "express";
2
- import { infoPage, infoJson } from "../controllers/info.controller.js";
3
-
4
- const router = express.Router();
5
-
6
- router.get(['/info', '/i'], infoPage);
7
- router.get(['/info.json', '/i.json'], infoJson);
8
-
9
- export default router;
1
+ import express from "express";
2
+ import { infoPage, infoJson } from "../controllers/info.controller.js";
3
+
4
+ const router = express.Router();
5
+
6
+ router.get(['/info', '/i'], infoPage);
7
+ router.get(['/info.json', '/i.json'], infoJson);
8
+
9
+ export default router;
@@ -1,20 +1,25 @@
1
- import express from "express";
2
- import { sessRole } from "mbkauthe";
3
- import { mbkbucketVar } from "../config/index.js";
4
- import { requireBucketView } from "../middleware/bucket-resolver.js";
5
- import { pviewRateLimit } from "../middleware/rate-limiter.js";
6
- import { pviewSecurity } from "../middleware/security.js";
7
- import { viewFile, playerPage, publicView } from "../controllers/view.controller.js";
8
-
9
- const router = express.Router();
10
- const adminAuth = sessRole('superadmin');
11
-
12
- router.use(requireBucketView);
13
- router.get('/player/*key', adminAuth, playerPage);
14
- router.get('/view/*key', adminAuth, viewFile);
15
-
16
- if (mbkbucketVar?.publiView_enabled) {
17
- router.get('/p_view/*key', pviewRateLimit, pviewSecurity, publicView);
18
- }
19
-
20
- export default router;
1
+ import express from "express";
2
+ import { sessRole } from "mbkauthe";
3
+ import { mbkbucketVar } from "../config/index.js";
4
+ import { requireBucketView } from "../middleware/bucket-resolver.js";
5
+ import { pviewRateLimit } from "../middleware/rate-limiter.js";
6
+ import { pviewSecurity } from "../middleware/security.js";
7
+ import { viewFile, playerPage, publicView } from "../controllers/view.controller.js";
8
+
9
+ export function createViewRoutes({ authorization = sessRole('superadmin') } = {}) {
10
+ const viewRouter = express.Router();
11
+
12
+ viewRouter.use(requireBucketView);
13
+ viewRouter.get('/player/*key', authorization, playerPage);
14
+ viewRouter.get('/view/*key', authorization, viewFile);
15
+
16
+ if (mbkbucketVar?.publiView_enabled) {
17
+ viewRouter.get('/p_view/*key', pviewRateLimit, pviewSecurity, publicView);
18
+ }
19
+
20
+ return viewRouter;
21
+ }
22
+
23
+ const router = createViewRoutes();
24
+
25
+ export default router;