instbyte 1.6.2 → 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.
- package/package.json +4 -3
- package/server/server.js +39 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "instbyte",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "A self-hosted LAN sharing utility for fast, frictionless file, link, and snippet exchange across devices — no cloud required.",
|
|
5
5
|
"main": "server/server.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"socket-io",
|
|
27
27
|
"sqlite"
|
|
28
28
|
],
|
|
29
|
-
"author": "
|
|
29
|
+
"author": "Mohit Gauniyal",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"repository": {
|
|
32
32
|
"type": "git",
|
|
@@ -39,9 +39,10 @@
|
|
|
39
39
|
"cookie-parser": "^1.4.6",
|
|
40
40
|
"express": "^4.18.2",
|
|
41
41
|
"express-rate-limit": "^7.1.5",
|
|
42
|
+
"helmet": "^8.1.0",
|
|
42
43
|
"multer": "^2.0.2",
|
|
43
44
|
"sharp": "^0.33.2",
|
|
44
45
|
"socket.io": "^4.6.1",
|
|
45
46
|
"sqlite3": "^5.1.6"
|
|
46
47
|
}
|
|
47
|
-
}
|
|
48
|
+
}
|
package/server/server.js
CHANGED
|
@@ -4,6 +4,7 @@ const os = require("os");
|
|
|
4
4
|
const net = require("net");
|
|
5
5
|
const cookieParser = require("cookie-parser");
|
|
6
6
|
const rateLimit = require("express-rate-limit");
|
|
7
|
+
const helmet = require("helmet");
|
|
7
8
|
|
|
8
9
|
let sharp = null;
|
|
9
10
|
try { sharp = require("sharp"); } catch (e) { }
|
|
@@ -26,6 +27,10 @@ const app = express();
|
|
|
26
27
|
const server = http.createServer(app);
|
|
27
28
|
const io = new Server(server, { cors: { origin: "*" } });
|
|
28
29
|
|
|
30
|
+
app.use(helmet({
|
|
31
|
+
contentSecurityPolicy: false // disable CSP for now — it would block CDN scripts
|
|
32
|
+
}));
|
|
33
|
+
|
|
29
34
|
app.use(express.json());
|
|
30
35
|
app.use(cookieParser());
|
|
31
36
|
app.use(requireAuth);
|
|
@@ -121,7 +126,7 @@ function requireAuth(req, res, next) {
|
|
|
121
126
|
if (!config.auth.passphrase) return next(); // no passphrase set, skip
|
|
122
127
|
|
|
123
128
|
// Allow the login route itself through
|
|
124
|
-
if (req.path === "/login" || req.path === "/info") return next();
|
|
129
|
+
if (req.path === "/login" || req.path === "/info" || req.path === "/health") return next();
|
|
125
130
|
|
|
126
131
|
|
|
127
132
|
// Check cookie
|
|
@@ -411,19 +416,27 @@ app.post("/channels", (req, res) => {
|
|
|
411
416
|
const { name } = req.body;
|
|
412
417
|
if (!name) return res.status(400).json({ error: "Name required" });
|
|
413
418
|
|
|
419
|
+
const trimmed = name.trim();
|
|
420
|
+
if (trimmed.length < 1 || trimmed.length > 32) {
|
|
421
|
+
return res.status(400).json({ error: "Channel name must be 1–32 characters" });
|
|
422
|
+
}
|
|
423
|
+
if (!/^[a-zA-Z0-9 _\-]+$/.test(trimmed)) {
|
|
424
|
+
return res.status(400).json({ error: "Only letters, numbers, spaces, hyphens, and underscores allowed" });
|
|
425
|
+
}
|
|
426
|
+
|
|
414
427
|
db.get("SELECT COUNT(*) as count FROM channels", (err, row) => {
|
|
415
428
|
|
|
416
429
|
if (row.count >= 10) {
|
|
417
430
|
return res.status(400).json({ error: "Max 10 channels allowed" });
|
|
418
431
|
}
|
|
419
432
|
|
|
420
|
-
db.run("INSERT INTO channels (name) VALUES (?)", [
|
|
433
|
+
db.run("INSERT INTO channels (name) VALUES (?)", [trimmed], function (err) {
|
|
421
434
|
|
|
422
435
|
if (err) {
|
|
423
436
|
return res.status(400).json({ error: "Channel exists" });
|
|
424
437
|
}
|
|
425
|
-
io.emit("channel-added", { id: this.lastID,
|
|
426
|
-
res.json({ id: this.lastID, name });
|
|
438
|
+
io.emit("channel-added", { id: this.lastID, trimmed });
|
|
439
|
+
res.json({ id: this.lastID, name: trimmed });
|
|
427
440
|
|
|
428
441
|
});
|
|
429
442
|
|
|
@@ -485,18 +498,25 @@ app.patch("/item/:id/move", (req, res) => {
|
|
|
485
498
|
app.patch("/channels/:name", (req, res) => {
|
|
486
499
|
const oldName = req.params.name;
|
|
487
500
|
const { name: newName } = req.body;
|
|
488
|
-
|
|
489
501
|
if (!newName) return res.status(400).json({ error: "Name required" });
|
|
490
502
|
|
|
503
|
+
const trimmed = newName.trim();
|
|
504
|
+
if (trimmed.length < 1 || trimmed.length > 32) {
|
|
505
|
+
return res.status(400).json({ error: "Channel name must be 1–32 characters" });
|
|
506
|
+
}
|
|
507
|
+
if (!/^[a-zA-Z0-9 _\-]+$/.test(trimmed)) {
|
|
508
|
+
return res.status(400).json({ error: "Only letters, numbers, spaces, hyphens, and underscores allowed" });
|
|
509
|
+
}
|
|
510
|
+
|
|
491
511
|
db.get("SELECT * FROM channels WHERE name=?", [oldName], (err, row) => {
|
|
492
512
|
if (!row) return res.status(404).json({ error: "Channel not found" });
|
|
493
513
|
|
|
494
|
-
db.run("UPDATE channels SET name=? WHERE name=?", [
|
|
514
|
+
db.run("UPDATE channels SET name=? WHERE name=?", [trimmed, oldName], (err) => {
|
|
495
515
|
if (err) return res.status(400).json({ error: "Channel name already exists" });
|
|
496
516
|
|
|
497
|
-
db.run("UPDATE items SET channel=? WHERE channel=?", [
|
|
498
|
-
io.emit("channel-renamed", { oldName, newName });
|
|
499
|
-
res.json({ oldName, newName });
|
|
517
|
+
db.run("UPDATE items SET channel=? WHERE channel=?", [trimmed, oldName], () => {
|
|
518
|
+
io.emit("channel-renamed", { oldName, newName: trimmed });
|
|
519
|
+
res.json({ oldName, newName: trimmed });
|
|
500
520
|
});
|
|
501
521
|
});
|
|
502
522
|
});
|
|
@@ -539,6 +559,15 @@ app.get("/branding", (req, res) => {
|
|
|
539
559
|
});
|
|
540
560
|
});
|
|
541
561
|
|
|
562
|
+
/* HEALTH MONITOR */
|
|
563
|
+
app.get("/health", (req, res) => {
|
|
564
|
+
res.json({
|
|
565
|
+
status: "ok",
|
|
566
|
+
uptime: Math.floor(process.uptime()),
|
|
567
|
+
version: require("../package.json").version
|
|
568
|
+
});
|
|
569
|
+
});
|
|
570
|
+
|
|
542
571
|
|
|
543
572
|
/* FAVICON */
|
|
544
573
|
app.get("/favicon-dynamic.png", async (req, res) => {
|
|
@@ -570,6 +599,7 @@ app.get("/favicon-dynamic.png", async (req, res) => {
|
|
|
570
599
|
});
|
|
571
600
|
|
|
572
601
|
|
|
602
|
+
|
|
573
603
|
/* LOGO */
|
|
574
604
|
app.get("/logo-dynamic.png", (req, res) => {
|
|
575
605
|
const b = config.branding;
|