mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 16:17:30 +00:00
Compare commits
3 Commits
v5.4.0alph
...
v4.5.0alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50af884563 | ||
|
|
0737c54a0e | ||
|
|
a7e516925c |
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>4.5.0alpha</version>
|
||||
<version>4.5.0alpha-4</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import spark.Request;
|
||||
|
||||
public abstract class AuthFramework {
|
||||
private static final String USER_SESSION_ID = "user";
|
||||
|
||||
public AuthFramework() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public void addAuthenticatedUser(Request request, User u) {
|
||||
request.session().attribute(USER_SESSION_ID, u);
|
||||
|
||||
}
|
||||
|
||||
public void removeAuthenticatedUser(Request request) {
|
||||
request.session().removeAttribute(USER_SESSION_ID);
|
||||
|
||||
}
|
||||
|
||||
public User getAuthenticatedUser(Request request) {
|
||||
return request.session().attribute(USER_SESSION_ID);
|
||||
}
|
||||
}
|
||||
@@ -18,20 +18,26 @@ import org.slf4j.LoggerFactory;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
public class BridgeSecurity extends AuthFramework {
|
||||
import spark.Request;
|
||||
|
||||
public class BridgeSecurity {
|
||||
private static final Logger log = LoggerFactory.getLogger(BridgeSecurity.class);
|
||||
private char[] habridgeKey;
|
||||
private static final String USER_SESSION_ID = "user";
|
||||
private static final byte[] SALT = {
|
||||
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
|
||||
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
|
||||
};
|
||||
private char[] habridgeKey;
|
||||
private BridgeSecurityDescriptor securityDescriptor;
|
||||
private boolean settingsChanged;
|
||||
|
||||
public BridgeSecurity(char[] theKey, String theData) {
|
||||
public BridgeSecurity(char[] theKey) {
|
||||
habridgeKey = theKey;
|
||||
securityDescriptor = null;
|
||||
settingsChanged = false;
|
||||
}
|
||||
|
||||
public void setSecurityData(String theData) {
|
||||
String anError = null;
|
||||
if(theData != null && !theData.isEmpty()) {
|
||||
try {
|
||||
@@ -211,4 +217,47 @@ public class BridgeSecurity extends AuthFramework {
|
||||
private static byte[] base64Decode(String property) throws IOException {
|
||||
return Base64.getDecoder().decode(property);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAuthenticatedUser(Request request, User u) {
|
||||
request.session().attribute(USER_SESSION_ID, u);
|
||||
|
||||
}
|
||||
|
||||
public void removeAuthenticatedUser(Request request) {
|
||||
request.session().removeAttribute(USER_SESSION_ID);
|
||||
|
||||
}
|
||||
|
||||
public User getAuthenticatedUser(Request request) {
|
||||
User theUser = request.session().attribute(USER_SESSION_ID);
|
||||
if(theUser == null) {
|
||||
String authHeader = request.headers("Authorization");
|
||||
if(authHeader != null) {
|
||||
byte[] authData;
|
||||
try {
|
||||
authData = base64Decode(authHeader.substring(6));
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
return theUser;
|
||||
}
|
||||
String[] credentials = new String(authData).split(":");
|
||||
String username = credentials[0];
|
||||
String password = credentials[1];
|
||||
theUser = new User();
|
||||
theUser.setUsername(username);
|
||||
theUser.setPassword(password);
|
||||
LoginResult theResult = null;
|
||||
try {
|
||||
theResult = validatePassword(theUser);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
return null;
|
||||
}
|
||||
if(theResult != null && theResult.getError() == null) {
|
||||
addAuthenticatedUser(request, theUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
return theUser;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,10 @@ public class BridgeSettings extends BackupHandler {
|
||||
bridgeControl = new BridgeControlDescriptor();
|
||||
theBridgeSettings = new BridgeSettingsDescriptor();
|
||||
bridgeSecurity = null;
|
||||
String theKey = System.getProperty("security.key");
|
||||
if(theKey == null)
|
||||
theKey = "IWantMyPasswordsToBeAbleToBeDecodedPleaseSeeTheReadme";
|
||||
bridgeSecurity = new BridgeSecurity(theKey.toCharArray());
|
||||
String ipV6Stack = System.getProperty("ipV6Stack");
|
||||
if(ipV6Stack == null || !ipV6Stack.equalsIgnoreCase("true")) {
|
||||
System.setProperty("java.net.preferIPv4Stack" , "true");
|
||||
@@ -183,10 +187,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
|
||||
setupInternalTestUser();
|
||||
|
||||
String theKey = System.getProperty("security.key");
|
||||
if(theKey == null)
|
||||
theKey = "IWantMyPasswordsToBeAbleToBeDecodedPleaseSeeTheReadme";
|
||||
bridgeSecurity = new BridgeSecurity(theKey.toCharArray(), theBridgeSettings.getSecurityData());
|
||||
bridgeSecurity.setSecurityData(theBridgeSettings.getSecurityData());
|
||||
}
|
||||
|
||||
public void loadConfig() {
|
||||
@@ -243,7 +244,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
|
||||
|
||||
private void configWriter(String content, Path filePath) {
|
||||
private synchronized void configWriter(String content, Path filePath) {
|
||||
if(Files.exists(filePath) && !Files.isWritable(filePath)){
|
||||
log.error("Error file is not writable: " + filePath);
|
||||
return;
|
||||
@@ -273,7 +274,8 @@ public class BridgeSettings extends BackupHandler {
|
||||
perms.add(PosixFilePermission.OWNER_WRITE);
|
||||
|
||||
try {
|
||||
if(System.getProperty("os.name").toLowerCase().indexOf("win") <= 0)
|
||||
String osName = System.getProperty("os.name");
|
||||
if(osName.toLowerCase().indexOf("win") < 0)
|
||||
Files.setPosixFilePermissions(filePath, perms);
|
||||
} catch(UnsupportedOperationException e) {
|
||||
log.info("Cannot set permissions for config file on this system as it is not supported. Continuing");
|
||||
|
||||
@@ -983,6 +983,9 @@ public class HueMulator {
|
||||
else
|
||||
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
||||
responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, state.getBri(), targetBri, targetBriInc, device, body);
|
||||
if(responseString != null && responseString.contains("{\"error\":")) {
|
||||
x = aMultiUtil.getSetCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
|
||||
public class CommandHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(CommandHome.class);
|
||||
private String execGarden;;
|
||||
private BridgeSettings theSettings;
|
||||
|
||||
public CommandHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
@@ -25,7 +25,7 @@ public class CommandHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int itensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
log.debug("Exec Request called with url: " + anItem.getItem().getAsString());
|
||||
log.debug("Exec Request called with url: " + anItem.getItem().getAsString() + " and exec Garden: " + (theSettings.getBridgeSecurity().getExecGarden() == null ? "not given" : theSettings.getBridgeSecurity().getExecGarden()));
|
||||
String responseString = null;
|
||||
String intermediate;
|
||||
if (anItem.getItem().getAsString().contains("exec://"))
|
||||
@@ -35,8 +35,10 @@ public class CommandHome implements Home {
|
||||
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, itensity, targetBri, targetBriInc, false);
|
||||
intermediate = DeviceDataDecode.replaceDeviceData(intermediate, device);
|
||||
intermediate = TimeDecode.replaceTimeValue(intermediate);
|
||||
if(execGarden != null) {
|
||||
if(System.getProperty("os.name").toLowerCase().indexOf("win") > 0)
|
||||
String execGarden = theSettings.getBridgeSecurity().getExecGarden();
|
||||
execGarden = execGarden.trim();
|
||||
if(execGarden != null && !execGarden.isEmpty()) {
|
||||
if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
|
||||
intermediate = execGarden + "\\" + intermediate;
|
||||
else
|
||||
intermediate = execGarden + "/" + intermediate;
|
||||
@@ -57,7 +59,7 @@ public class CommandHome implements Home {
|
||||
Process p = Runtime.getRuntime().exec(anItem);
|
||||
log.debug("Process running: " + p.isAlive());
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not execute request: " + anItem, e);
|
||||
log.warn("Could not execute request: " + anItem + " with message: " + e.getMessage());
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Error on calling out to device\", \"parameter\": \"/lights/" + lightId
|
||||
+ "state\"}}]";
|
||||
@@ -75,7 +77,7 @@ public class CommandHome implements Home {
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
log.info("Command Home for system program execution created.");
|
||||
this.execGarden = bridgeSettings.getBridgeSecurity().getExecGarden();
|
||||
this.theSettings = bridgeSettings;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
<li class="dropdown">
|
||||
<a id="dLabel1" href="" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Help <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="dLabel">
|
||||
<li><a href="#!/login">Login/Logout</a></li>
|
||||
<li><a href="https://github.com/bwssytems/ha-bridge/blob/master/README.md" target="_blank">Readme</a></li>
|
||||
<li><a href="https://github.com/bwssytems/ha-bridge/wiki/HA-Bridge-FAQs" target="_blank">FAQ</a></li>
|
||||
</ul>
|
||||
@@ -64,6 +63,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#!/login">Login/Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -94,13 +94,22 @@ app.run( async function ($rootScope, $location, Auth, bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('$routeChangeStart', function (event, next) {
|
||||
$rootScope.$on('securityReview', function(event, data) {
|
||||
if(Auth.isLoggedIn()) {
|
||||
bridgeService.loadBridgeSettings();
|
||||
bridgeService.getTestUser();
|
||||
bridgeService.getSecurityInfo();
|
||||
bridgeService.viewMapTypes();
|
||||
$location.path("/");
|
||||
} else {
|
||||
event.preventDefault();
|
||||
$location.path("/login");
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('securityReinit', function(event, data) {
|
||||
event.preventDefault();
|
||||
Auth.logout();
|
||||
$location.path("/login");
|
||||
});
|
||||
|
||||
$rootScope.$on('$routeChangeStart', function (event, next) {
|
||||
if (!Auth.checkPermissionForView(next)){
|
||||
event.preventDefault();
|
||||
$location.path("/login");
|
||||
@@ -870,10 +879,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
return $http.get(this.state.bridgelocation + "/description.xml").then(
|
||||
function (response) {
|
||||
ngToast.dismiss(self.state.myToastMsg);
|
||||
self.viewConfigs();
|
||||
self.state.myToastMsg = null;
|
||||
self.state.isInControl = false;
|
||||
window.location.reload();
|
||||
$rootScope.$broadcast('securityReinit', 'done');
|
||||
},
|
||||
function (error) {
|
||||
setTimeout(function(){
|
||||
@@ -2905,7 +2913,6 @@ app.controller('SomfyController', function ($scope, $location, bridgeService, ng
|
||||
});
|
||||
|
||||
app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
bridgeService.viewMapTypes();
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.onDevices = null;
|
||||
@@ -3213,6 +3220,7 @@ app.filter('configuredSomfyDevices', function (bridgeService) {
|
||||
|
||||
app.controller('LoginController', function ($scope, $location, Auth) {
|
||||
$scope.failed = false;
|
||||
$scope.loggedIn = Auth.isLoggedIn();
|
||||
$scope.login = function(username, password) {
|
||||
Auth.login(username, password)
|
||||
.then(function() {
|
||||
@@ -3224,6 +3232,8 @@ app.controller('LoginController', function ($scope, $location, Auth) {
|
||||
|
||||
$scope.logout = function() {
|
||||
Auth.logout();
|
||||
$scope.loggedIn = Auth.isLoggedIn();
|
||||
$location.path("/login");
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<h2 class="panel-title">Login</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="form-container">
|
||||
<div ng-if="!loggedIn" class="form-container">
|
||||
|
||||
<form name="loginForm" role="form">
|
||||
<legend class="form-label">Enter Credentials</legend>
|
||||
@@ -18,10 +18,12 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button type="button" class="btn btn-success" ng-click="login(username, password)">Submit</button>
|
||||
<button type="button" class="btn btn-danger" ng-click="logout()">Logout</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div ng-if="loggedIn">
|
||||
<button type="button" class="btn btn-danger" ng-click="logout()">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,16 +48,9 @@
|
||||
<button ng-disabled="bridge.isInControl"
|
||||
class="btn btn-success" type="submit" ng-click="saveSettings()">Save</button>
|
||||
<button ng-disabled="bridge.isInControl" class="btn btn-warning"
|
||||
type="submit" ng-click="bridgeReinit()">Bridge
|
||||
Reinitialize</button>
|
||||
type="submit" ng-click="bridgeReinit()">Bridge Reinitialize</button>
|
||||
<button ng-disabled="bridge.isInControl" class="btn btn-danger"
|
||||
type="submit" ng-click="bridgeStop()">Bridge Stop</button>
|
||||
<button class="btn btn-primary" type="submit" onclick="myRefresh()">Refresh</button>
|
||||
<script>
|
||||
function myRefresh() {
|
||||
location.reload();
|
||||
}
|
||||
</script>
|
||||
<button class="btn btn-warning"
|
||||
type="submit" ng-click="changeSeuritySettings()">Update Security Settings</button>
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user