Skip to content

Commit cf287f5

Browse files
authored
Refactor Hyperion JSON-API (#1727)
1 parent 94850d8 commit cf287f5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4184
-2943
lines changed

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
### Breaking
1010

11+
**JSON-API**
12+
- Align JSON subscription update elements. `ledcolors-imagestream-update, ledcolors-ledstream-update, logmsg-update` now return data via `data` and not `result
13+
1114
### Added
1215

1316
- Support gaps on Matrix Layout (#1696)
1417

18+
**JSON-API**
19+
- New subscription support for event updates, i.e. `Suspend, Resume, Idle, idleResume, Restart, Quit`.
20+
- Support direct or multiple instance addressing via single requests (#809)
21+
- Support of `serverinfo` subcommands: `getInfo, subscribe, unsubscribe, getSubscriptions, getSubscriptionCommands`
22+
- [Overview](https://github.com/hyperion-project/hyperion.ng/blob/API_Auth/doc/development/JSON-API%20_Commands_Overview.md) of API commands and subscription updates
23+
1524
### Changed
1625

26+
- Fixed: Cross Site Scripting Vulnerability (CVE-2024-4174, CVE-2024-4175)
27+
- Fixed: hyperion-v4l2 taking screenshot failed (#1722)
28+
- Nanoleaf: Support new devices and do not restore ExtControl state
29+
- Workaround to address Web UI keeps forcing browser to download the html instead (#1692)
30+
- Fixed: Kodi Color Calibration, Refactor Wizards (#1674)
31+
- Fixed: Token Dialog not closing
32+
33+
**JSON-API**
34+
- Refactored JSON-API to ensure consistent authorization behaviour across sessions and single requests with token authorization.
35+
- Provide additional error details with API responses, esp. on JSON parsing, validation or token errors.
36+
- Generate random TANs for every API request from the Hyperion UI
37+
- Fixed: Handling of IP4 addresses wrapped in IPv6 for external network connections-
38+
1739
### Removed
1840

41+
**JSON-API**
42+
- Removed ability to enable/disable local admin authorization. All admin commands require authorization, i.e. `authorize-adminRequired` will always be `true`.
43+
- Removed `session-updates` subscription
44+
- `serverinfo/subscribe` element will be deprecated and replaced by corresponding subcommand
45+
1946
## [2.0.16](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.16) - 2024-01
2047

2148
### Added

assets/webconfig/i18n/en.json

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@
186186
"conf_network_json_intro": "The JSON-RPC-Port of all Hyperion instances, used for remote control.",
187187
"conf_network_net_intro": "Network related settings which are applied to all network services.",
188188
"conf_network_proto_intro": "The PROTO-Port of all Hyperion instances, used for picture streams (HyperionScreenCap, Kodi Addon, Android Hyperion Grabber, ...)",
189+
"conf_network_tok_idhead": "ID",
189190
"conf_network_tok_cidhead": "Description",
190191
"conf_network_tok_comment_title": "Token description",
191192
"conf_network_tok_desc": "Tokens grant other applications access to the Hyperion API, an application can request a token where you need to accept it or you create them on your own below. These tokens are just required when \"API Authorization\" is enabled in network settings.",
@@ -500,19 +501,16 @@
500501
"edt_conf_log_level_expl": "Depending on loglevel you see less or more messages in your log.",
501502
"edt_conf_log_level_title": "Log-Level",
502503
"edt_conf_net_apiAuth_expl": "Enforce all applications that use the Hyperion API to authenticate themself against Hyperion (Exception: see \"Local API Authentication\"). Higher security, as you control the access and revoke it at any time.",
503-
"edt_conf_net_apiAuth_title": "API Authentication",
504504
"edt_conf_net_heading_title": "Network",
505-
"edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Webinterface from the internet. Disable for higher security.",
505+
"edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Web Interface from the Internet. Disable for increased security.",
506506
"edt_conf_net_internetAccessAPI_title": "Internet API Access",
507-
"edt_conf_net_ipWhitelist_expl": "You can whitelist IP addresses instead allowing all connections from internet to connect to the Hyperion API/Webinterface.",
508-
"edt_conf_net_ipWhitelist_title": "Whitelisted IP's",
507+
"edt_conf_net_ipWhitelist_expl": "Define whitelisted IP addresses from which API requests from the Internet are allowed. All other external connections will be denied.",
508+
"edt_conf_net_ipWhitelist_title": "Whitelisted IP addresses",
509509
"edt_conf_net_ip_itemtitle": "IP",
510-
"edt_conf_net_localAdminAuth_expl": "When enabled, administration access from your local network needs a password.",
511-
"edt_conf_net_localAdminAuth_title": "Local Admin API Authentication",
512-
"edt_conf_net_localApiAuth_expl": "When enabled, connections from your home network needs to authenticate themselves against Hyperion with a token.",
510+
"edt_conf_net_localApiAuth_expl": "When disabled, API authorisation via password or token is not required for local connections. The exception is administrative commands.",
513511
"edt_conf_net_localApiAuth_title": "Local API Authentication",
514-
"edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict the access to the API through the internet to certain IP's.",
515-
"edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP's",
512+
"edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict API requests over the Internet to only those IP addresses on the whitelist.",
513+
"edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP addresses",
516514
"edt_conf_os_events_lockEnable_title": "Listen to lock events",
517515
"edt_conf_os_events_lockEnable_expl": "Listen to screen lock/unlock events",
518516
"edt_conf_os_events_suspendEnable_title": "Listen to suspend events",

assets/webconfig/js/content_index.js

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,30 @@ $(document).ready(function () {
7373
//End language selection
7474

7575
$(window.hyperion).on("cmd-authorize-tokenRequest cmd-authorize-getPendingTokenRequests", function (event) {
76-
var val = event.response.info;
77-
if (Array.isArray(event.response.info)) {
78-
if (event.response.info.length == 0) {
79-
return
76+
77+
if (event.response && event.response.info !== undefined) {
78+
var val = event.response.info;
79+
80+
if (Array.isArray(event.response.info)) {
81+
if (event.response.info.length == 0) {
82+
return
83+
}
84+
val = event.response.info[0]
85+
if (val.comment == '')
86+
$('#modal_dialog').modal('hide');
8087
}
81-
val = event.response.info[0]
82-
if (val.comment == '')
83-
$('#modal_dialog').modal('hide');
84-
}
8588

86-
showInfoDialog("grantToken", $.i18n('conf_network_tok_grantT'), $.i18n('conf_network_tok_grantMsg') + '<br><span style="font-weight:bold">App: ' + val.comment + '</span><br><span style="font-weight:bold">Code: ' + val.id + '</span>')
87-
$("#tok_grant_acc").off().on('click', function () {
88-
tokenList.push(val)
89-
// forward event, in case we need to rebuild the list now
90-
$(window.hyperion).trigger({ type: "build-token-list" });
91-
requestHandleTokenRequest(val.id, true)
92-
});
93-
$("#tok_deny_acc").off().on('click', function () {
94-
requestHandleTokenRequest(val.id, false)
95-
});
89+
showInfoDialog("grantToken", $.i18n('conf_network_tok_grantT'), $.i18n('conf_network_tok_grantMsg') + '<br><span style="font-weight:bold">App: ' + val.comment + '</span><br><span style="font-weight:bold">Code: ' + val.id + '</span>')
90+
$("#tok_grant_acc").off().on('click', function () {
91+
tokenList.push(val)
92+
// forward event, in case we need to rebuild the list now
93+
$(window.hyperion).trigger({ type: "build-token-list" });
94+
requestHandleTokenRequest(val.id, true)
95+
});
96+
$("#tok_deny_acc").off().on('click', function () {
97+
requestHandleTokenRequest(val.id, false)
98+
});
99+
}
96100
});
97101

98102
$(window.hyperion).one("cmd-authorize-getTokenList", function (event) {
@@ -186,21 +190,12 @@ $(document).ready(function () {
186190
}
187191
});
188192

189-
$(window.hyperion).on("cmd-authorize-adminRequired", function (event) {
190-
//Check if a admin login is required.
191-
//If yes: check if default pw is set. If no: go ahead to get server config and render page
192-
if (event.response.info.adminRequired === true)
193-
requestRequiresDefaultPasswortChange();
194-
else
195-
requestServerConfigSchema();
196-
});
197-
198193
$(window.hyperion).on("error", function (event) {
199194
//If we are getting an error "No Authorization" back with a set loginToken we will forward to new Login (Token is expired.
200195
//e.g.: hyperiond was started new in the meantime)
201196
if (event.reason == "No Authorization" && getStorage("loginToken")) {
202197
removeStorage("loginToken");
203-
requestRequiresAdminAuth();
198+
requestRequiresDefaultPasswortChange();
204199
}
205200
else if (event.reason == "Selected Hyperion instance isn't running") {
206201
//Switch to default instance
@@ -211,7 +206,7 @@ $(document).ready(function () {
211206
});
212207

213208
$(window.hyperion).on("open", function (event) {
214-
requestRequiresAdminAuth();
209+
requestRequiresDefaultPasswortChange();
215210
});
216211

217212
$(window.hyperion).on("ready", function (event) {

assets/webconfig/js/content_logging.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ var createdCont = false;
33
var isScroll = true;
44

55
performTranslation();
6-
requestLoggingStop();
76

87
$(document).ready(function () {
98

9+
window.addEventListener('hashchange', function(event) {
10+
requestLoggingStop();
11+
});
12+
1013
requestLoggingStart();
1114

1215
$('#conf_cont').append(createOptPanel('fa-reorder', $.i18n("edt_conf_log_heading_title"), 'editor_container', 'btn_submit'));
@@ -178,9 +181,9 @@ $(document).ready(function () {
178181
if (!window.loggingHandlerInstalled) {
179182
window.loggingHandlerInstalled = true;
180183

181-
$(window.hyperion).on("cmd-logging-update", function (event) {
184+
$(window.hyperion).on("cmd-logmsg-update", function (event) {
182185

183-
var messages = (event.response.result.messages);
186+
var messages = (event.response.data.messages);
184187

185188
if (messages.length != 0) {
186189
if (!createdCont) {

assets/webconfig/js/content_network.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,13 @@ $(document).ready(function () {
213213
for (var key in tokenList) {
214214
var lastUse = (tokenList[key].last_use) ? tokenList[key].last_use : "-";
215215
var btn = '<button id="tok' + tokenList[key].id + '" type="button" class="btn btn-danger">' + $.i18n('general_btn_delete') + '</button>';
216-
$('.tktbody').append(createTableRow([tokenList[key].comment, lastUse, btn], false, true));
216+
$('.tktbody').append(createTableRow([tokenList[key].id, tokenList[key].comment, lastUse, btn], false, true));
217217
$('#tok' + tokenList[key].id).off().on('click', handleDeleteToken);
218218
}
219219
}
220220

221221
createTable('tkthead', 'tktbody', 'tktable');
222-
$('.tkthead').html(createTableRow([$.i18n('conf_network_tok_cidhead'), $.i18n('conf_network_tok_lastuse'), $.i18n('general_btn_delete')], true, true));
222+
$('.tkthead').html(createTableRow([$.i18n('conf_network_tok_idhead'), $.i18n('conf_network_tok_cidhead'), $.i18n('conf_network_tok_lastuse'), $.i18n('general_btn_delete')], true, true));
223223
buildTokenList();
224224

225225
function handleDeleteToken(e) {

assets/webconfig/js/hyperion.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ function sendToHyperion(command, subcommand, msg)
177177
else
178178
msg = "";
179179

180+
window.wsTan = Math.floor(Math.random() * 1000)
180181
window.websocket.send('{"command":"'+command+'", "tan":'+window.wsTan+subcommand+msg+'}');
181182
}
182183

@@ -187,7 +188,7 @@ function sendToHyperion(command, subcommand, msg)
187188
// data: The json data as Object
188189
// tan: The optional tan, default 1. If the tan is -1, we skip global response error handling
189190
// Returns data of response or false if timeout
190-
async function sendAsyncToHyperion (command, subcommand, data, tan = 1) {
191+
async function sendAsyncToHyperion (command, subcommand, data, tan = Math.floor(Math.random() * 1000) ) {
191192
let obj = { command, tan }
192193
if (subcommand) {Object.assign(obj, {subcommand})}
193194
if (data) { Object.assign(obj, data) }
@@ -486,38 +487,38 @@ async function requestLedDeviceDiscovery(type, params)
486487
{
487488
let data = { ledDeviceType: type, params: params };
488489

489-
return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) );
490+
return sendAsyncToHyperion("leddevice", "discover", data);
490491
}
491492

492493
async function requestLedDeviceProperties(type, params)
493494
{
494495
let data = { ledDeviceType: type, params: params };
495496

496-
return sendAsyncToHyperion("leddevice", "getProperties", data, Math.floor(Math.random() * 1000));
497+
return sendAsyncToHyperion("leddevice", "getProperties", data);
497498
}
498499

499500
function requestLedDeviceIdentification(type, params)
500501
{
501502
let data = { ledDeviceType: type, params: params };
502503

503-
return sendAsyncToHyperion("leddevice", "identify", data, Math.floor(Math.random() * 1000));
504+
return sendAsyncToHyperion("leddevice", "identify", data);
504505
}
505506

506507
async function requestLedDeviceAddAuthorization(type, params) {
507508
let data = { ledDeviceType: type, params: params };
508509

509-
return sendAsyncToHyperion("leddevice", "addAuthorization", data, Math.floor(Math.random() * 1000));
510+
return sendAsyncToHyperion("leddevice", "addAuthorization", data);
510511
}
511512

512513
async function requestInputSourcesDiscovery(type, params) {
513514
let data = { sourceType: type, params: params };
514515

515-
return sendAsyncToHyperion("inputsource", "discover", data, Math.floor(Math.random() * 1000));
516+
return sendAsyncToHyperion("inputsource", "discover", data);
516517
}
517518

518519
async function requestServiceDiscovery(type, params) {
519520
let data = { serviceType: type, params: params };
520521

521-
return sendAsyncToHyperion("service", "discover", data, Math.floor(Math.random() * 1000));
522+
return sendAsyncToHyperion("service", "discover", data);
522523
}
523524

assets/webconfig/js/ledsim.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ $(document).ready(function () {
261261
$("body").get(0).style.setProperty("--background-var", "none");
262262
}
263263
else {
264-
printLedsToCanvas(event.response.result.leds)
264+
printLedsToCanvas(event.response.data.leds)
265265
$("body").get(0).style.setProperty("--background-var", "url(" + ($('#leds_preview_canv')[0]).toDataURL("image/jpg") + ") no-repeat top left");
266266
}
267267
});
@@ -275,7 +275,7 @@ $(document).ready(function () {
275275
}
276276
}
277277
else {
278-
var imageData = (event.response.result.image);
278+
var imageData = (event.response.data.image);
279279

280280
var image = new Image();
281281
image.onload = function () {

assets/webconfig/js/ui_utils.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,9 @@ function showInfoDialog(type, header, message) {
319319
});
320320

321321
$(document).on('click', '[data-dismiss-modal]', function () {
322-
var target = $(this).attr('data-dismiss-modal');
323-
$.find(target).modal('hide');
324-
});
322+
var target = $(this).data('dismiss-modal');
323+
$($.find(target)).modal('hide');
324+
});
325325
}
326326

327327
function createHintH(type, text, container) {

config/hyperion.config.json.default

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,7 @@
220220
"internetAccessAPI": false,
221221
"restirctedInternetAccessAPI": false,
222222
"ipWhitelist": [],
223-
"apiAuth": true,
224-
"localApiAuth": false,
225-
"localAdminAuth": true
223+
"localApiAuth": false
226224
},
227225

228226
"ledConfig": {

0 commit comments

Comments
 (0)