From 4ecbad6558cdc6331d8cb6c556c177be228c11ce Mon Sep 17 00:00:00 2001 From: Admin Date: Tue, 12 Dec 2017 15:21:45 -0600 Subject: [PATCH] Fixed enable rooms for Alexa. Removed huemulator redirect for Spark. Added Link management as links are now stored with IP. --- pom.xml | 4 +- .../bwssystems/HABridge/BridgeSecurity.java | 6 ++ .../com/bwssystems/HABridge/HABridge.java | 2 +- .../bwssystems/HABridge/SystemControl.java | 34 ++++++++ .../devicemanagmeent/DeviceResource.java | 5 +- .../bwssystems/HABridge/hue/HueMulator.java | 39 +++------ src/main/resources/public/scripts/app.js | 79 ++++++++++++++++++- .../resources/public/views/configuration.html | 1 + .../public/views/managelinksdialog.html | 32 ++++++++ 9 files changed, 165 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/public/views/managelinksdialog.html diff --git a/pom.xml b/pom.xml index 1b22967..a55b325 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 5.0.0a + 5.1.0 jar HA Bridge @@ -63,7 +63,7 @@ com.sparkjava spark-core - 2.3 + 2.7.1 slf4j-simple diff --git a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java index a91db6b..6e883e5 100644 --- a/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java +++ b/src/main/java/com/bwssystems/HABridge/BridgeSecurity.java @@ -205,6 +205,12 @@ public class BridgeSecurity { return securityDescriptor.getWhitelist(); } + public void setWhitelist(Map aWhitelist) { + securityDescriptor.setWhitelist(aWhitelist); + settingsChanged = true; + return; + } + public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) { String validUser = null; boolean found = false; diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java index 72cd939..55b48cf 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -62,7 +62,7 @@ public class HABridge { // sparkjava config directive to set port for the web server to listen on port(bridgeSettings.getBridgeSettingsDescriptor().getServerPort()); staticFileLocation("/public"); -// initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort())); + initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort())); if(!bridgeSettings.getBridgeControl().isReinit()) init(); bridgeSettings.getBridgeControl().setReinit(false); diff --git a/src/main/java/com/bwssystems/HABridge/SystemControl.java b/src/main/java/com/bwssystems/HABridge/SystemControl.java index c7210fb..e66e898 100644 --- a/src/main/java/com/bwssystems/HABridge/SystemControl.java +++ b/src/main/java/com/bwssystems/HABridge/SystemControl.java @@ -8,6 +8,7 @@ import static spark.Spark.before; import static spark.Spark.halt; import java.io.IOException; +import java.lang.reflect.Type; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; @@ -16,11 +17,13 @@ import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Timer; import java.util.Base64; +import java.util.Map; import org.apache.http.HttpStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.bwssystems.HABridge.api.hue.WhitelistEntry; import com.bwssystems.HABridge.dao.BackupFilename; import com.bwssystems.HABridge.util.JsonTransformer; import com.bwssystems.HABridge.util.TextStringFormatter; @@ -28,6 +31,7 @@ import com.bwssystems.logservices.LoggerInfo; import com.bwssystems.logservices.LoggingForm; import com.bwssystems.logservices.LoggingManager; import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.spi.ILoggingEvent; @@ -295,6 +299,36 @@ public class SystemControl { return bridgeSettings.getBridgeSecurity().getSecurityInfo(); }, new JsonTransformer()); + // http://ip_address:port/system/whitelist gets the whitelist for the bridge + get (SYSTEM_CONTEXT + "/whitelist", (request, response) -> { + log.debug("Get whitelist"); + response.status(HttpStatus.SC_OK); + response.type("application/json"); + return bridgeSettings.getBridgeSecurity().getWhitelist(); + }, new JsonTransformer()); + +// http://ip_address:port/system/setwhitelist CORS request + options(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> { + response.status(HttpStatus.SC_OK); + response.header("Access-Control-Allow-Origin", request.headers("Origin")); + response.header("Access-Control-Allow-Methods", "GET, POST, PUT"); + response.header("Access-Control-Allow-Headers", request.headers("Access-Control-Request-Headers")); + response.header("Content-Type", "text/html; charset=utf-8"); + return ""; + }); +// http://ip_address:port/system/setwhitelist which sets the whitelist after being managed + post(SYSTEM_CONTEXT + "/setwhitelist", (request, response) -> { + log.debug("setwhitelist...."); + Type listType = new TypeToken>() { + }.getType(); + Map aWhitelist = new Gson().fromJson(request.body(), listType); + bridgeSettings.getBridgeSecurity().setWhitelist(aWhitelist); + bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor()); + response.status(HttpStatus.SC_OK); + response.type("application/json"); + return bridgeSettings.getBridgeSecurity().getWhitelist(); + }, new JsonTransformer()); + // http://ip_address:port/system/logmgmt/update CORS request options(SYSTEM_CONTEXT + "/logmgmt/update", (request, response) -> { response.status(HttpStatus.SC_OK); diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index 99a3743..849ec21 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -48,10 +48,7 @@ public class DeviceResource { public DeviceResource(BridgeSettings theSettings, HomeManager aHomeManager) { bridgeSettings = theSettings; this.deviceRepository = new DeviceRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpDeviceDb()); - if(bridgeSettings.getBridgeSettingsDescriptor().isUserooms()) - this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb()); - else - this.groupRepository = null; + this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb()); homeManager = aHomeManager; aGsonHandler = new GsonBuilder().create(); setupEndpoints(); diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index c0e07a0..8c59d40 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -76,10 +76,11 @@ public class HueMulator { public void setupServer() { log.info("Hue emulator service started...."); before(HUE_CONTEXT + "/*", (request, response) -> { - String path = request.pathInfo(); - if (path.endsWith("/")) { // it should work with or without a trailing slash - response.redirect(path.substring(0, path.length() - 1)); - } + // This currently causes an error with Spark replies +// String path = request.pathInfo(); +// if (path.endsWith("/")) { // it should work with or without a trailing slash +// response.redirect(path.substring(0, path.length() - 1)); +// } log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>"); if(bridgeSettingMaster.getBridgeSecurity().isSecure()) { String pathInfo = request.pathInfo(); @@ -127,12 +128,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return addGroup(request.params(":userid"), request.ip(), request.body()); - } else { - log.debug("group add requested from (No Use Rooms) " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"success\":{\"id\":\"1\"}}]"; - } + return addGroup(request.params(":userid"), request.ip(), request.body()); }); // http://ip_address:port/api/:userid/groups/ // delete a group @@ -140,12 +136,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip()); - } else { - log.debug("delete to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; - } + return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip()); }); // http://ip_address:port/api/:userid/groups/ // modify a single group @@ -153,12 +144,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body()); - } else { - log.debug("put to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; - } + return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body()); }); // http://ip_address:port/api/:userid/groups//action // group acions @@ -166,12 +152,7 @@ public class HueMulator { response.header("Access-Control-Allow-Origin", request.headers("Origin")); response.type("application/json"); response.status(HttpStatus.SC_OK); - if(bridgeSettings.isUserooms()) { - return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); - } else { - log.debug("put action to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body()); - return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]"; - } + return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false); }); // http://ip_address:port/api/{userId}/scenes returns json objects of // all scenes configured @@ -1022,7 +1003,7 @@ public class HueMulator { if (theErrors != null) return theErrors; - if (Integer.parseInt(lightId) >= 10000) { + if (bridgeSettings.isUserooms() && Integer.parseInt(lightId) >= 10000) { GroupDescriptor group = groupRepository.findOne(String.valueOf(Integer.parseInt(lightId) - 10000)); return DeviceResponse.createResponseForVirtualLight(group); } diff --git a/src/main/resources/public/scripts/app.js b/src/main/resources/public/scripts/app.js index 1a539ee..5c4bc52 100644 --- a/src/main/resources/public/scripts/app.js +++ b/src/main/resources/public/scripts/app.js @@ -277,6 +277,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n return $http.post(this.state.huebase, "{\"devicetype\":\"test_ha_bridge\"}").then( function (response) { self.state.testuser = response.data[0].success.username; + self.getWhitelist(); }, function (error) { if (error.status === 401) @@ -318,7 +319,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n if (error.status === 401) $rootScope.$broadcast('securityReinit', 'done'); else - self.displayWarn("Update ecurity settings Error: ", error); + self.displayWarn("Update security settings Error: ", error); } ); }; @@ -410,6 +411,29 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n ); }; + this.getWhitelist = function () { + return $http.get(this.state.systemsbase + "/whitelist").then( + function (response) { + self.state.whitelist = response.data; + }, + function (error) { + self.displayWarn("Cannot get swhitelist: ", error); + } + ); + }; + + this.setWhitelist = function (whitelist) { + return $http.post(this.state.systemsbase + "/setwhitelist", whitelist ).then( + function (response) { + self.state.whitelist = response.data; + self.displaySuccess("Updated whitelist.") + }, + function (error) { + self.displayWarn("Update whitelist Error: ", error); + } + ); + }; + this.aContainsB = function (a, b) { return a.indexOf(b) >= 0; } @@ -1141,6 +1165,18 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n }; + this.saveSettingsNoReinit = function () { + return $http.put(this.state.systemsbase + "/settings", this.state.settings).then( + function (response) { + self.displaySuccess("Save Settings completed."); + }, + function (error) { + self.displayWarn("Save Settings Error: ", error); + } + ); + + }; + this.backupSettings = function (afilename) { return $http.put(this.state.systemsbase + "/backup/create", { filename: afilename @@ -1699,6 +1735,40 @@ app.controller('SecurityDialogCtrl', function ($scope, bridgeService, ngDialog) }; }); +app.controller('ManageLinksDialogCtrl', function ($scope, bridgeService, ngDialog) { + bridgeService.getWhitelist(); + $scope.whitelist = bridgeService.state.whitelist; + + $scope.setWhitelist = function () { + bridgeService.setWhitelist($scope.whitelist); + ngDialog.close('ngdialog1'); + }; + + $scope.delEntry = function (anEntry) { + for(var key in $scope.whitelist) { + if ($scope.whitelist.hasOwnProperty(key)) { + var theEntry = $scope.whitelist[key]; + if(theEntry.name === anEntry) { + delete $scope.whitelist[key]; + } + } + } + }; + + $scope.refresh = function () { + bridgeService.getWhitelist(); + $scope.whitelist = bridgeService.state.whitelist; + } + + $scope.delAll = function () { + $scope.whitelist = null; + }; + + $scope.dismissDialog = function () { + ngDialog.close('ngdialog1'); + }; +}); + app.controller('LogsController', function ($scope, $location, bridgeService) { bridgeService.viewLogs(); $scope.bridge = bridgeService.state; @@ -1807,6 +1877,13 @@ app.controller('ViewingController', function ($scope, $location, bridgeService, $scope.pushLinkButton = function() { bridgeService.pushLinkButton(); }; + $scope.manageLinksButton = function() { + ngDialog.open({ + template: 'views/managelinksdialog.html', + controller: 'ManageLinksDialogCtrl', + className: 'ngdialog-theme-default' + }); + }; $scope.backupDeviceDb = function (optionalbackupname) { bridgeService.backupDeviceDb(optionalbackupname); }; diff --git a/src/main/resources/public/views/configuration.html b/src/main/resources/public/views/configuration.html index 96b73a6..030aeb9 100644 --- a/src/main/resources/public/views/configuration.html +++ b/src/main/resources/public/views/configuration.html @@ -39,6 +39,7 @@
+ diff --git a/src/main/resources/public/views/managelinksdialog.html b/src/main/resources/public/views/managelinksdialog.html new file mode 100644 index 0000000..a928d03 --- /dev/null +++ b/src/main/resources/public/views/managelinksdialog.html @@ -0,0 +1,32 @@ +
+ +
+ Manage Links +
+ + + + + + + + + + + + + + +
NameCreate DateManage
{{linkItem.name}}{{linkItem.createDate}}
+
+
+
+ + + + +
+
+ +
\ No newline at end of file