homebridge-openwrt-control 0.3.6 → 0.3.8
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/CHANGELOG.md +7 -0
- package/README.md +2 -0
- package/config.schema.json +12 -1
- package/package.json +3 -3
- package/src/restful.js +22 -0
- package/src/router.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
- After update to v0.1.0 the plugin need to be reconfigured!
|
|
11
11
|
|
|
12
|
+
## [0.3.8] - (23.09.2026)
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- optional RESTful access `Token`. When set, every request (GET and POST) must send the header `Authorization: Bearer <token>`, otherwise the server responds `401`. Leaving it empty keeps the previous behaviour, so existing configs keep working
|
|
17
|
+
- readme update
|
|
18
|
+
|
|
12
19
|
## [0.3.6] - (11.05.2026)
|
|
13
20
|
|
|
14
21
|
## Changes
|
package/README.md
CHANGED
|
@@ -99,6 +99,7 @@
|
|
|
99
99
|
| `restFul{}` | RESTFul object. |
|
|
100
100
|
| `restFul.enable` | If enabled, RESTful server will start automatically and respond to any path request. |
|
|
101
101
|
| `restFul.port` | Here set the listening `Port` for RESTful server. |
|
|
102
|
+
| `restFul.token` | Here optional set the access token. When set, every request must send the header `Authorization: Bearer <token>`, otherwise the server responds `401`. |
|
|
102
103
|
| `mqtt{}` | MQTT object. |
|
|
103
104
|
| `mqtt.enable` | If enabled, MQTT Broker will start automatically and publish all available data. |
|
|
104
105
|
| `mqtt.host` | Here set the `IP Address` or `Hostname` for MQTT Broker. |
|
|
@@ -113,6 +114,7 @@
|
|
|
113
114
|
### REST Integration
|
|
114
115
|
|
|
115
116
|
REST POST calls must include a content-type header of `application/json`.
|
|
117
|
+
If `Token` is set, every request (GET and POST) must send the header `Authorization: Bearer <token>`.
|
|
116
118
|
Path `status` response all available paths.
|
|
117
119
|
|
|
118
120
|
| Method | URL | Path | Response | Type |
|
package/config.schema.json
CHANGED
|
@@ -478,6 +478,16 @@
|
|
|
478
478
|
"condition": {
|
|
479
479
|
"functionBody": "return model.devices[arrayIndices].restFul.enable == true;"
|
|
480
480
|
}
|
|
481
|
+
},
|
|
482
|
+
"token": {
|
|
483
|
+
"title": "Token",
|
|
484
|
+
"type": "string",
|
|
485
|
+
"placeholder": "optional",
|
|
486
|
+
"description": "Optional access token. When set, every request must send the header 'Authorization: Bearer <token>'. Leave empty to keep the server open on the local network.",
|
|
487
|
+
"format": "password",
|
|
488
|
+
"condition": {
|
|
489
|
+
"functionBody": "return model.devices[arrayIndices].restFul.enable == true;"
|
|
490
|
+
}
|
|
481
491
|
}
|
|
482
492
|
}
|
|
483
493
|
},
|
|
@@ -782,7 +792,8 @@
|
|
|
782
792
|
"title": "RESTFul",
|
|
783
793
|
"items": [
|
|
784
794
|
"devices[].restFul.enable",
|
|
785
|
-
"devices[].restFul.port"
|
|
795
|
+
"devices[].restFul.port",
|
|
796
|
+
"devices[].restFul.token"
|
|
786
797
|
]
|
|
787
798
|
},
|
|
788
799
|
{
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"displayName": "OpenWrt Control",
|
|
3
3
|
"name": "homebridge-openwrt-control",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.8",
|
|
5
5
|
"description": "Homebridge plugin to control OpenWrt flashed devices.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "grzegorz914",
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"node": "^20 || ^22 || ^24 || ^25 || ^26"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"mqtt": "^5.15.
|
|
38
|
-
"axios": "^1.
|
|
37
|
+
"mqtt": "^5.15.2",
|
|
38
|
+
"axios": "^1.20.0",
|
|
39
39
|
"express": "^5.2.1"
|
|
40
40
|
},
|
|
41
41
|
"keywords": [
|
package/src/restful.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import express, { json } from 'express';
|
|
2
2
|
import EventEmitter from 'events';
|
|
3
|
+
import { createHash, timingSafeEqual } from 'crypto';
|
|
3
4
|
|
|
4
5
|
const DEFAULT_MESSAGE = 'This data is not available at this time.';
|
|
5
6
|
|
|
@@ -7,6 +8,7 @@ class RestFul extends EventEmitter {
|
|
|
7
8
|
constructor(config) {
|
|
8
9
|
super();
|
|
9
10
|
this.port = config.port;
|
|
11
|
+
this.token = typeof config.token === 'string' ? config.token.trim() : '';
|
|
10
12
|
this.logWarn = config.logWarn;
|
|
11
13
|
this.logDebug = config.logDebug;
|
|
12
14
|
|
|
@@ -23,6 +25,19 @@ class RestFul extends EventEmitter {
|
|
|
23
25
|
app.set('json spaces', 2);
|
|
24
26
|
app.use(json());
|
|
25
27
|
|
|
28
|
+
// Optional token auth, when a token is configured every route requires "Authorization: Bearer <token>"
|
|
29
|
+
if (this.token) {
|
|
30
|
+
app.use((req, res, next) => {
|
|
31
|
+
const header = req.headers.authorization ?? '';
|
|
32
|
+
const provided = header.startsWith('Bearer ') ? header.slice(7) : '';
|
|
33
|
+
if (!this.tokenValid(provided)) {
|
|
34
|
+
if (this.logWarn) this.emit('warn', `RESTFul Unauthorized request from: ${req.ip}, ${req.method} ${req.path}`);
|
|
35
|
+
return res.status(401).json({ error: 'RESTFul Unauthorized' });
|
|
36
|
+
}
|
|
37
|
+
next();
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
26
41
|
// Register GET routes for all keys
|
|
27
42
|
for (const key of Object.keys(this.restFulData)) {
|
|
28
43
|
app.get(`/${key}`, (req, res) => {
|
|
@@ -71,6 +86,13 @@ class RestFul extends EventEmitter {
|
|
|
71
86
|
}
|
|
72
87
|
}
|
|
73
88
|
|
|
89
|
+
tokenValid(provided) {
|
|
90
|
+
// Compare fixed-length hashes so the check takes the same time regardless of token length or content
|
|
91
|
+
const a = createHash('sha256').update(provided).digest();
|
|
92
|
+
const b = createHash('sha256').update(this.token).digest();
|
|
93
|
+
return timingSafeEqual(a, b);
|
|
94
|
+
}
|
|
95
|
+
|
|
74
96
|
update(path, data) {
|
|
75
97
|
if (Object.hasOwn(this.restFulData, path)) {
|
|
76
98
|
this.restFulData[path] = data;
|
package/src/router.js
CHANGED