mbkbucket 1.1.2 → 1.2.1
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.
- package/index.d.ts +1 -1
- package/index.js +22 -0
- package/lib/bucket.js +26 -7
- package/lib/s3.js +2 -1
- package/package.json +2 -2
- package/public/bucketadmin.css +1488 -0
- package/public/bucketadmin.js +1515 -0
- package/views/bucket.handlebars +1 -1
- package/views/bucketadmincontent.handlebars +40 -2718
- package/views/info.handlebars +1056 -0
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -8,16 +8,22 @@ import compression from "compression";
|
|
|
8
8
|
import rateLimit from 'express-rate-limit';
|
|
9
9
|
import bucket from "./lib/bucket.js";
|
|
10
10
|
import { checkVersion } from "./lib/config/index.js";
|
|
11
|
+
import { appVersion } from "./lib/config/index.js";
|
|
11
12
|
|
|
12
13
|
dotenv.config();
|
|
13
14
|
|
|
14
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
16
|
const __dirname = path.dirname(__filename);
|
|
17
|
+
const assetVersion = appVersion;
|
|
16
18
|
|
|
17
19
|
const server = express();
|
|
18
20
|
server.set('trust proxy', 1);
|
|
19
21
|
|
|
20
22
|
server.use(compression());
|
|
23
|
+
server.use((req, res, next) => {
|
|
24
|
+
res.locals.assetVersion = assetVersion;
|
|
25
|
+
next();
|
|
26
|
+
});
|
|
21
27
|
|
|
22
28
|
// Rate limiting: general limiter for typical browsing/API usage and a stricter
|
|
23
29
|
// limiter for dashboard (admin) routes.
|
|
@@ -34,6 +40,22 @@ const generalLimiter = rateLimit({
|
|
|
34
40
|
server.use(express.json());
|
|
35
41
|
server.use(express.urlencoded({ extended: true }));
|
|
36
42
|
|
|
43
|
+
// Serve only specific static assets (limit exposure): CSS and JS used by the dashboard
|
|
44
|
+
// This replaces serving the entire /public directory.
|
|
45
|
+
const staticMaxAgeSeconds = 90 * 24 * 60 * 60; // 90 days
|
|
46
|
+
server.get('/mbkbucket/bucketadmin.css', (req, res) => {
|
|
47
|
+
res.set('Cache-Control', `public, max-age=${staticMaxAgeSeconds}, immutable`);
|
|
48
|
+
res.sendFile(path.join(__dirname, 'public', 'bucketadmin.css'), (err) => {
|
|
49
|
+
if (err) res.status(err.status || 404).end();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
server.get('/mbkbucket/bucketadmin.js', (req, res) => {
|
|
53
|
+
res.set('Cache-Control', `public, max-age=${staticMaxAgeSeconds}, immutable`);
|
|
54
|
+
res.sendFile(path.join(__dirname, 'public', 'bucketadmin.js'), (err) => {
|
|
55
|
+
if (err) res.status(err.status || 404).end();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
37
59
|
// Configure Handlebars (single setup)
|
|
38
60
|
server.engine("handlebars", engine({
|
|
39
61
|
extname: ".handlebars",
|
package/lib/bucket.js
CHANGED
|
@@ -6,6 +6,7 @@ import path from "path";
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import os from 'os';
|
|
8
8
|
import crypto from 'crypto';
|
|
9
|
+
import { appVersion, getLatestVersion } from "./config/index.js";
|
|
9
10
|
|
|
10
11
|
const router = express.Router();
|
|
11
12
|
const upload = multer({ storage: multer.memoryStorage() });
|
|
@@ -17,7 +18,17 @@ fs.mkdirSync(CHUNKS_DIR, { recursive: true });
|
|
|
17
18
|
// Key/prefix helpers are provided by `s3.js`: `ensurePrefix`, `ensureKeyHasAppPrefix`, `getAppName`.
|
|
18
19
|
|
|
19
20
|
router.get('/mbkbucket', validateSessionAndRole('SuperAdmin'), async (req, res) => {
|
|
20
|
-
renderPage(req, res, "bucket.handlebars", false, { page: "Admin Bucket", bucketvar: mbkautheVar?.bucket, message: req.query.message, error: req.query.error });
|
|
21
|
+
renderPage(req, res, "bucket.handlebars", false, { page: "Admin Bucket", bucketvar: mbkautheVar?.bucket, APP_NAME: mbkautheVar?.APP_NAME, message: req.query.message, error: req.query.error });
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
router.get(['/mbkbucket/info', "/mbkbucket/i"], validateSessionAndRole('SuperAdmin'), async (req, res) => {
|
|
25
|
+
let latestVersion = 'unknown';
|
|
26
|
+
try {
|
|
27
|
+
latestVersion = await getLatestVersion();
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error("[mbkauthe] Error fetching package-lock.json:", err);
|
|
30
|
+
}
|
|
31
|
+
renderPage(req, res, "info.handlebars", false, { page: "MBK Bucket Info", appVersion, latestVersion, APP_NAME: mbkautheVar?.APP_NAME });
|
|
21
32
|
});
|
|
22
33
|
|
|
23
34
|
// API endpoint for fetching files
|
|
@@ -34,11 +45,20 @@ router.get('/mbkbucket/api/files', validateSessionAndRole('SuperAdmin'), async (
|
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
try {
|
|
37
|
-
|
|
38
|
-
let
|
|
48
|
+
let files = [];
|
|
49
|
+
let continuationToken = undefined;
|
|
39
50
|
let usedPrefix = effectivePrefix;
|
|
40
51
|
let legacyFallback = false;
|
|
41
52
|
|
|
53
|
+
// Fetch all files recursively (handling S3 pagination)
|
|
54
|
+
do {
|
|
55
|
+
const result = await listfiles(effectivePrefix, { continuationToken });
|
|
56
|
+
if (result.Contents) {
|
|
57
|
+
files = files.concat(result.Contents);
|
|
58
|
+
}
|
|
59
|
+
continuationToken = result.nextToken;
|
|
60
|
+
} while (continuationToken);
|
|
61
|
+
|
|
42
62
|
// If no files found under the app prefixed path, try root as a legacy fallback
|
|
43
63
|
if (!files.length) {
|
|
44
64
|
try {
|
|
@@ -58,8 +78,7 @@ router.get('/mbkbucket/api/files', validateSessionAndRole('SuperAdmin'), async (
|
|
|
58
78
|
if (search.trim()) {
|
|
59
79
|
const searchLower = search.toLowerCase();
|
|
60
80
|
files = files.filter(file => {
|
|
61
|
-
|
|
62
|
-
return fileName.toLowerCase().includes(searchLower);
|
|
81
|
+
return file.Key.toLowerCase().includes(searchLower);
|
|
63
82
|
});
|
|
64
83
|
}
|
|
65
84
|
|
|
@@ -187,9 +206,9 @@ router.post('/mbkbucket/upload-complete', validateSessionAndRole('SuperAdmin'),
|
|
|
187
206
|
|
|
188
207
|
// Cleanup chunks
|
|
189
208
|
for (const f of files) {
|
|
190
|
-
await fs.promises.unlink(path.join(dir, f)).catch(() => {});
|
|
209
|
+
await fs.promises.unlink(path.join(dir, f)).catch(() => { });
|
|
191
210
|
}
|
|
192
|
-
await fs.promises.rmdir(dir).catch(() => {});
|
|
211
|
+
await fs.promises.rmdir(dir).catch(() => { });
|
|
193
212
|
|
|
194
213
|
return res.json({ success: true, message: 'File uploaded successfully (assembled)', key });
|
|
195
214
|
} catch (err) {
|
package/lib/s3.js
CHANGED
|
@@ -216,13 +216,14 @@ export async function uploadFile(key, fileBuffer, contentType, options = {}) {
|
|
|
216
216
|
|
|
217
217
|
// Download file with enhanced features
|
|
218
218
|
export async function downloadFile(key, options = {}) {
|
|
219
|
+
let keyToDownload;
|
|
219
220
|
try {
|
|
220
221
|
if (!key) {
|
|
221
222
|
throw new Error('Key is required');
|
|
222
223
|
}
|
|
223
224
|
|
|
224
225
|
// Ensure key is app-prefixed
|
|
225
|
-
|
|
226
|
+
keyToDownload = ensureKeyHasAppPrefix(key);
|
|
226
227
|
|
|
227
228
|
const {
|
|
228
229
|
range = null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mbkbucket",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "S3 Bucket manager for mbktech.org apps",
|
|
5
5
|
"author": "Muhammad Bin Khalid",
|
|
6
6
|
"homepage": "https://github.com/MIbnEKhalid/mbkbucket#readme",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"express": "^4.22.1",
|
|
20
20
|
"express-handlebars": "^8.0.3",
|
|
21
21
|
"express-rate-limit": "^7.0.1",
|
|
22
|
-
"mbkauthe": "
|
|
22
|
+
"mbkauthe": "latest",
|
|
23
23
|
"multer": "^2.0.2",
|
|
24
24
|
"pg": "^8.16.3"
|
|
25
25
|
},
|