Compare commits

...

6 Commits

Author SHA1 Message Date
Admin
13c84ba174 Hopefully, final testing release 2017-04-06 16:23:14 -05:00
Admin
b19fe5c86a Took care of dynamic test user creation 2017-04-05 16:02:40 -05:00
Admin
ff9d0a5a77 Moving to release candidate 1 2017-04-04 15:54:58 -05:00
Admin
50af884563 Added settings write synchronization 2017-04-04 13:08:34 -05:00
Admin
0737c54a0e Updated security changes for exec command with the exec garden. 2017-04-04 11:47:04 -05:00
Admin
a7e516925c Updated security to have basic auth and also remove login when reinit
happens.
2017-04-03 16:40:46 -05:00
18 changed files with 506 additions and 248 deletions

View File

@@ -214,10 +214,15 @@ The default ip address for the bridge to listen on is all interfaces (0.0.0.0).
java -jar -Dserver.ip=192.168.1.1 ha-bridge-W.X.Y.jar java -jar -Dserver.ip=192.168.1.1 ha-bridge-W.X.Y.jar
``` ```
### -Dsecurity.key=`<Your Key To Encrypt Security Data>` ### -Dsecurity.key=`<Your Key To Encrypt Security Data>`
The default security key is encoded into the Java code. This should not be used as anyone with access to the code can decode your passworsd. To override what the default , specify -Dsecurity.key=`<Your Key To Encrypt Security Data>` explicitly on the command line. This is will prevent any issues if your config file gets haced. The command line example: The default security key is encoded into the Java code. The default should not be used as anyone with access to the code can decode your password. To override what the default , specify -Dsecurity.key=`<Your Key To Encrypt Security Data>` explicitly on the command line. This is will prevent any issues if your config file gets hacked. The command line example:
``` ```
java -jar -Dsecurity.key=Xfawer354WertSdf321234asd ha-bridge-W.X.Y.jar java -jar -Dsecurity.key=Xfawer354WertSdf321234asd ha-bridge-W.X.Y.jar
``` ```
### -Dexec.garden=`<The path to your scripts and program directory>`
The default exec garden path is not set which allows any program or script to be called. The default should not be used as anyone with access to the your system can create a exec command call and execute it from the api. To override what the default , specify -Dexec.garden=`<The path to your scripts and program directory>` explicitly on the command line. This is will prevent any issues if your system file gets hacked. The command line example:
```
java -jar -Dexec.garden=C:\Users\John\bin
```
## HA Bridge Usage and Configuration ## HA Bridge Usage and Configuration
This section will cover the basics of configuration and where this configuration can be done. This requires that you have started your bridge process and then have pointed your This section will cover the basics of configuration and where this configuration can be done. This requires that you have started your bridge process and then have pointed your
favorite web interface by going to the http://<my ip address>:<port> or http://localhost:<port> with port you have assigned. The default quick link is http://localhost for your reference. favorite web interface by going to the http://<my ip address>:<port> or http://localhost:<port> with port you have assigned. The default quick link is http://localhost for your reference.
@@ -225,6 +230,10 @@ favorite web interface by going to the http://<my ip address>:<port> or http://l
This screen allows you to see your devices you have configured for the ha-bridge to present to a controller, such as an Amazon Echo/Dot. It gives you a count of devices as there have been reports that the Echo only supports a limited number, but has been growing as of late, YMMV. You can test each device from this page as this calls the ha-bridge just as a controller would, i.e. the Echo. This is useful to make sure your configuration for each device is correct and for trouble shooting. You can also manages your devices as well by editing and making a new device copy as well as deleting it. This screen allows you to see your devices you have configured for the ha-bridge to present to a controller, such as an Amazon Echo/Dot. It gives you a count of devices as there have been reports that the Echo only supports a limited number, but has been growing as of late, YMMV. You can test each device from this page as this calls the ha-bridge just as a controller would, i.e. the Echo. This is useful to make sure your configuration for each device is correct and for trouble shooting. You can also manages your devices as well by editing and making a new device copy as well as deleting it.
At the bottom of the screen is the "Bridge Device DB Backup" which can be accessed with clicking on the `+` to expand this frame. Here you can backup and restore configurations that you have saved. These configs can be named or by clicking the `Backup Device DB' button will create a backup and name it for you. You can manage these backups by restoring them or deleting them. At the bottom of the screen is the "Bridge Device DB Backup" which can be accessed with clicking on the `+` to expand this frame. Here you can backup and restore configurations that you have saved. These configs can be named or by clicking the `Backup Device DB' button will create a backup and name it for you. You can manage these backups by restoring them or deleting them.
#### Renumber Devices
This changes the numbering of the added devices to start at 1 and goes up from there. It was originally intended for a conversion from the previous system version that used large numbers and was not necessary. This also allows the system to try and number sequentially. If you use this button, you will need to re-discover your devices as their ID's will have changed.
#### Link
If this is present, you have enabled the ue link button feature for the ha-bridge. If you want a new system to recognize the ha-bridge, you will need to press this button when you are doign a discovery.
### The Bridge Control Tab ### The Bridge Control Tab
This is where all of the configuration occurs for what ports and IP's the bridge runs on. It also contains the configurations for target devices so that Helper Tabs for configuration can be added as well as the connection information to control those devices. This is where all of the configuration occurs for what ports and IP's the bridge runs on. It also contains the configurations for target devices so that Helper Tabs for configuration can be added as well as the connection information to control those devices.
#### Bridge server #### Bridge server
@@ -232,7 +241,7 @@ This field is used to test the bridge server with the UPNP IP Address and to mak
#### Bridge Control Buttons #### Bridge Control Buttons
These buttons are for managing the bridge. The Save button is enabled when there is a change to the configuration. The Bridge Reinitialize button will recycle the internal running of the bridge in the java process. The Stop button will stop the java process. The Refresh button will refresh the page and settings. These buttons are for managing the bridge. The Save button is enabled when there is a change to the configuration. The Bridge Reinitialize button will recycle the internal running of the bridge in the java process. The Stop button will stop the java process. The Refresh button will refresh the page and settings.
#### The Security Dialog #### The Security Dialog
This is where you can set the different security settings for the ha-bridge. This is where you can set the different security settings for the ha-bridge. There are two settings, one for enabling Hue like operation to secure the Hue api with the internally generated user for the calls that are done after the link button. The other is to secure the hue api with a username/password that is created as well. The other fields are to add and delete users and to set and change passwords for those users. If there are no users in the system, the system will not require a username/password to operate.
#### Configuration Path and File #### Configuration Path and File
The default location for the configuration file to contain the settings for the bridge is the relative path from where the bridge is started in "data/habridge.config". If you would like a different filename or directory, specify `<directory>/<filename>` explicitly. The default location for the configuration file to contain the settings for the bridge is the relative path from where the bridge is started in "data/habridge.config". If you would like a different filename or directory, specify `<directory>/<filename>` explicitly.
#### Device DB Path and File #### Device DB Path and File

View File

@@ -5,7 +5,7 @@
<groupId>com.bwssystems.HABridge</groupId> <groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId> <artifactId>ha-bridge</artifactId>
<version>4.5.0alpha</version> <version>4.5.0rc3</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>HA Bridge</name> <name>HA Bridge</name>

View File

@@ -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);
}
}

View File

@@ -5,6 +5,12 @@ import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Base64; import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.UUID;
import java.util.Map.Entry;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
@@ -15,23 +21,36 @@ import javax.crypto.spec.PBEParameterSpec;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.api.hue.HueError;
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; 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 static final Logger log = LoggerFactory.getLogger(BridgeSecurity.class);
private char[] habridgeKey; private static final String USER_SESSION_ID = "user";
private static final String DEPRACATED_INTERNAL_USER = "thehabridgeuser";
private static final String TEST_USER_TYPE = "test_ha_bridge";
private static final byte[] SALT = { private static final byte[] SALT = {
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
}; };
private char[] habridgeKey;
private String execGarden;
private BridgeSecurityDescriptor securityDescriptor; private BridgeSecurityDescriptor securityDescriptor;
private boolean settingsChanged; private boolean settingsChanged;
public BridgeSecurity(char[] theKey, String theData) { public BridgeSecurity(char[] theKey, String theExecGarden) {
habridgeKey = theKey; habridgeKey = theKey;
execGarden = theExecGarden;
securityDescriptor = null; securityDescriptor = null;
settingsChanged = false; settingsChanged = false;
}
public void setSecurityData(String theData) {
String anError = null; String anError = null;
if(theData != null && !theData.isEmpty()) { if(theData != null && !theData.isEmpty()) {
try { try {
@@ -43,6 +62,7 @@ public class BridgeSecurity extends AuthFramework {
} catch (IOException e) { } catch (IOException e) {
anError = e.getMessage(); anError = e.getMessage();
} }
if(anError != null)
log.warn("Cound not get security data, using default security (none): " + anError); log.warn("Cound not get security data, using default security (none): " + anError);
} }
@@ -123,13 +143,8 @@ public class BridgeSecurity extends AuthFramework {
return error; return error;
} }
public void setExecGarden(String theGarden) {
securityDescriptor.setExecGarden(theGarden);
settingsChanged = true;
}
public String getExecGarden() { public String getExecGarden() {
return securityDescriptor.getExecGarden(); return execGarden;
} }
public void setUseLinkButton(boolean useThis) { public void setUseLinkButton(boolean useThis) {
securityDescriptor.setUseLinkButton(useThis); securityDescriptor.setUseLinkButton(useThis);
@@ -145,7 +160,6 @@ public class BridgeSecurity extends AuthFramework {
} }
public SecurityInfo getSecurityInfo() { public SecurityInfo getSecurityInfo() {
SecurityInfo theInfo = new SecurityInfo(); SecurityInfo theInfo = new SecurityInfo();
theInfo.setExecGarden(getExecGarden());
theInfo.setUseLinkButton(isUseLinkButton()); theInfo.setUseLinkButton(isUseLinkButton());
theInfo.setSecureHueApi(isSecureHueApi()); theInfo.setSecureHueApi(isSecureHueApi());
theInfo.setSecure(isSecure()); theInfo.setSecure(isSecure());
@@ -188,6 +202,91 @@ public class BridgeSecurity extends AuthFramework {
this.settingsChanged = settingsChanged; this.settingsChanged = settingsChanged;
} }
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
String validUser = null;
boolean found = false;
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
&& !aUser.equalsIgnoreCase("")) {
if (securityDescriptor.getWhitelist() != null) {
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
Iterator<String> userIterator = theUserIds.iterator();
while (userIterator.hasNext()) {
validUser = userIterator.next();
if (validUser.equals(aUser))
found = true;
}
}
}
if(!found && !strict) {
newWhitelistUser(aUser, userDescription);
found = true;
}
if (!found) {
return HueErrorResponse.createResponse("1", "/api/" + aUser, "unauthorized user", null, null, null).getTheErrors();
}
Object anUser = securityDescriptor.getWhitelist().remove(DEPRACATED_INTERNAL_USER);
if(anUser != null)
setSettingsChanged(true);
return null;
}
public void newWhitelistUser(String aUser, String userDescription) {
if(aUser.equals(DEPRACATED_INTERNAL_USER))
return;
if (securityDescriptor.getWhitelist() == null) {
securityDescriptor.setWhitelist(new HashMap<>());
}
if(userDescription == null)
userDescription = "auto insert user";
securityDescriptor.getWhitelist().put(aUser, WhitelistEntry.createEntry(userDescription));
setSettingsChanged(true);
}
public String createWhitelistUser(String userDescription) {
String aUser = getNewUserID();
newWhitelistUser(aUser, userDescription);
return aUser;
}
public void convertWhitelist(Map<String, WhitelistEntry> whitelist) {
securityDescriptor.setWhitelist(whitelist);
}
private String getNewUserID() {
UUID uid = UUID.randomUUID();
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
String newUser = "";
while (st.hasMoreTokens()) {
newUser = newUser + st.nextToken();
}
return newUser;
}
public void removeTestUsers() {
if (securityDescriptor.getWhitelist() != null) {
Object anUser = securityDescriptor.getWhitelist().remove(DEPRACATED_INTERNAL_USER);
if(anUser != null)
setSettingsChanged(true);
Iterator<Entry<String, WhitelistEntry>> it = securityDescriptor.getWhitelist().entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, WhitelistEntry> pair = it.next();
it.remove(); // avoids a ConcurrentModificationException
if(pair.getValue().getName().equals(TEST_USER_TYPE)) {
securityDescriptor.getWhitelist().remove(pair.getKey());
setSettingsChanged(true);
}
}
}
}
private String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException { private String encrypt(String property) throws GeneralSecurityException, UnsupportedEncodingException {
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(habridgeKey)); SecretKey key = keyFactory.generateSecret(new PBEKeySpec(habridgeKey));
@@ -211,4 +310,47 @@ public class BridgeSecurity extends AuthFramework {
private static byte[] base64Decode(String property) throws IOException { private static byte[] base64Decode(String property) throws IOException {
return Base64.getDecoder().decode(property); 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;
}
} }

View File

@@ -1,12 +1,14 @@
package com.bwssystems.HABridge; package com.bwssystems.HABridge;
import java.util.Map; import java.util.Map;
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
public class BridgeSecurityDescriptor { public class BridgeSecurityDescriptor {
private Map<String, User> users; private Map<String, User> users;
private boolean useLinkButton; private boolean useLinkButton;
private String execGarden; private String execGarden;
private boolean secureHueApi; private boolean secureHueApi;
private Map<String, WhitelistEntry> whitelist;
public BridgeSecurityDescriptor() { public BridgeSecurityDescriptor() {
super(); super();
@@ -44,6 +46,12 @@ public class BridgeSecurityDescriptor {
public void setSecureHueApi(boolean secureHueApi) { public void setSecureHueApi(boolean secureHueApi) {
this.secureHueApi = secureHueApi; this.secureHueApi = secureHueApi;
} }
public Map<String, WhitelistEntry> getWhitelist() {
return whitelist;
}
public void setWhitelist(Map<String, WhitelistEntry> whitelist) {
this.whitelist = whitelist;
}
public boolean isSecure() { public boolean isSecure() {
boolean secureFlag = false; boolean secureFlag = false;

View File

@@ -12,6 +12,8 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption; import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.PosixFilePermission;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@@ -29,12 +31,18 @@ public class BridgeSettings extends BackupHandler {
private BridgeSettingsDescriptor theBridgeSettings; private BridgeSettingsDescriptor theBridgeSettings;
private BridgeControlDescriptor bridgeControl; private BridgeControlDescriptor bridgeControl;
private BridgeSecurity bridgeSecurity; private BridgeSecurity bridgeSecurity;
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
public BridgeSettings() { public BridgeSettings() {
super(); super();
bridgeControl = new BridgeControlDescriptor(); bridgeControl = new BridgeControlDescriptor();
theBridgeSettings = new BridgeSettingsDescriptor(); theBridgeSettings = new BridgeSettingsDescriptor();
bridgeSecurity = null; bridgeSecurity = null;
String theKey = System.getProperty("security.key");
if(theKey == null)
theKey = "IWantMyPasswordsToBeAbleToBeDecodedPleaseSeeTheReadme";
String execGarden = System.getProperty("exec.garden");
bridgeSecurity = new BridgeSecurity(theKey.toCharArray(), execGarden);
String ipV6Stack = System.getProperty("ipV6Stack"); String ipV6Stack = System.getProperty("ipV6Stack");
if(ipV6Stack == null || !ipV6Stack.equalsIgnoreCase("true")) { if(ipV6Stack == null || !ipV6Stack.equalsIgnoreCase("true")) {
System.setProperty("java.net.preferIPv4Stack" , "true"); System.setProperty("java.net.preferIPv4Stack" , "true");
@@ -50,6 +58,10 @@ public class BridgeSettings extends BackupHandler {
public BridgeSecurity getBridgeSecurity() { public BridgeSecurity getBridgeSecurity() {
return bridgeSecurity; return bridgeSecurity;
} }
public static String getCurrentDate() {
return dateFormat.format(new Date());
}
public void buildSettings() { public void buildSettings() {
String addressString = null; String addressString = null;
String theVeraAddress = null; String theVeraAddress = null;
@@ -135,7 +147,7 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setNestpwd(System.getProperty("nest.pwd")); theBridgeSettings.setNestpwd(System.getProperty("nest.pwd"));
} }
if(theBridgeSettings.getUpnpConfigAddress() == null || theBridgeSettings.getUpnpConfigAddress().equals("")) { if(theBridgeSettings.getUpnpConfigAddress() == null || theBridgeSettings.getUpnpConfigAddress().trim().equals("") || theBridgeSettings.getUpnpConfigAddress().trim().equals("0.0.0.0")) {
addressString = checkIpAddress(null, true); addressString = checkIpAddress(null, true);
if(addressString != null) { if(addressString != null) {
theBridgeSettings.setUpnpConfigAddress(addressString); theBridgeSettings.setUpnpConfigAddress(addressString);
@@ -181,12 +193,12 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setWebaddress(serverIpOverride); theBridgeSettings.setWebaddress(serverIpOverride);
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-"); setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
setupInternalTestUser(); bridgeSecurity.setSecurityData(theBridgeSettings.getSecurityData());
if(theBridgeSettings.getWhitelist() != null) {
String theKey = System.getProperty("security.key"); bridgeSecurity.convertWhitelist(theBridgeSettings.getWhitelist());
if(theKey == null) theBridgeSettings.removeWhitelist();
theKey = "IWantMyPasswordsToBeAbleToBeDecodedPleaseSeeTheReadme"; updateConfigFile();
bridgeSecurity = new BridgeSecurity(theKey.toCharArray(), theBridgeSettings.getSecurityData()); }
} }
public void loadConfig() { public void loadConfig() {
@@ -219,11 +231,11 @@ public class BridgeSettings extends BackupHandler {
try { try {
newBridgeSettings.setSecurityData(bridgeSecurity.getSecurityDescriptorData()); newBridgeSettings.setSecurityData(bridgeSecurity.getSecurityDescriptorData());
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block log.warn("could not get encoded security data: " + e.getMessage());
e.printStackTrace(); return;
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// TODO Auto-generated catch block log.warn("could not get encoded security data: " + e.getMessage());
e.printStackTrace(); return;
} }
bridgeSecurity.setSettingsChanged(false); bridgeSecurity.setSettingsChanged(false);
} }
@@ -237,13 +249,25 @@ public class BridgeSettings extends BackupHandler {
log.debug("Save HA Bridge settings."); log.debug("Save HA Bridge settings.");
Path configPath = Paths.get(theBridgeSettings.getConfigfile()); Path configPath = Paths.get(theBridgeSettings.getConfigfile());
JsonTransformer aRenderer = new JsonTransformer(); JsonTransformer aRenderer = new JsonTransformer();
if(bridgeSecurity.isSettingsChanged()) {
try {
theBridgeSettings.setSecurityData(bridgeSecurity.getSecurityDescriptorData());
} catch (UnsupportedEncodingException e) {
log.warn("could not get encoded security data: " + e.getMessage());
return;
} catch (GeneralSecurityException e) {
log.warn("could not get encoded security data: " + e.getMessage());
return;
}
bridgeSecurity.setSettingsChanged(false);
}
String jsonValue = aRenderer.render(theBridgeSettings); String jsonValue = aRenderer.render(theBridgeSettings);
configWriter(jsonValue, configPath); configWriter(jsonValue, configPath);
_loadConfig(configPath); _loadConfig(configPath);
} }
private void configWriter(String content, Path filePath) { private synchronized void configWriter(String content, Path filePath) {
if(Files.exists(filePath) && !Files.isWritable(filePath)){ if(Files.exists(filePath) && !Files.isWritable(filePath)){
log.error("Error file is not writable: " + filePath); log.error("Error file is not writable: " + filePath);
return; return;
@@ -260,7 +284,7 @@ public class BridgeSettings extends BackupHandler {
try { try {
Path target = null; Path target = null;
if(Files.exists(filePath)) { if(Files.exists(filePath)) {
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "habridge.config.old"); target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "habridge.config.old." + getCurrentDate());
Files.move(filePath, target); Files.move(filePath, target);
} }
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE); Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
@@ -273,7 +297,8 @@ public class BridgeSettings extends BackupHandler {
perms.add(PosixFilePermission.OWNER_WRITE); perms.add(PosixFilePermission.OWNER_WRITE);
try { 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); Files.setPosixFilePermissions(filePath, perms);
} catch(UnsupportedOperationException e) { } catch(UnsupportedOperationException e) {
log.info("Cannot set permissions for config file on this system as it is not supported. Continuing"); log.info("Cannot set permissions for config file on this system as it is not supported. Continuing");
@@ -309,6 +334,7 @@ public class BridgeSettings extends BackupHandler {
log.error("checkIpAddress cannot get ip address of this host, Exiting with message: " + e.getMessage(), e); log.error("checkIpAddress cannot get ip address of this host, Exiting with message: " + e.getMessage(), e);
return null; return null;
} }
String addressString = null; String addressString = null;
InetAddress address = null; InetAddress address = null;
while (ifs.hasMoreElements() && addressString == null) { while (ifs.hasMoreElements() && addressString == null) {
@@ -335,9 +361,4 @@ public class BridgeSettings extends BackupHandler {
} }
return addressString; return addressString;
} }
private void setupInternalTestUser() {
theBridgeSettings.setupInternalTestUser();
if(theBridgeSettings.isSettingsChanged())
this.updateConfigFile();
}
} }

View File

@@ -1,58 +1,105 @@
package com.bwssystems.HABridge; package com.bwssystems.HABridge;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import com.google.gson.annotations.Expose;
import java.util.StringTokenizer; import com.google.gson.annotations.SerializedName;
import java.util.UUID;
import com.bwssystems.HABridge.api.hue.HueConstants; import com.bwssystems.HABridge.api.hue.HueConstants;
import com.bwssystems.HABridge.api.hue.HueError;
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
import com.bwssystems.HABridge.api.hue.WhitelistEntry; import com.bwssystems.HABridge.api.hue.WhitelistEntry;
public class BridgeSettingsDescriptor { public class BridgeSettingsDescriptor {
private static final String DEFAULT_INTERNAL_USER = "thehabridgeuser"; @SerializedName("upnpconfigaddress")
private static final String DEFAULT_USER_DESCRIPTION = "default_test_user"; @Expose
private String upnpconfigaddress; private String upnpconfigaddress;
@SerializedName("serverport")
@Expose
private Integer serverport; private Integer serverport;
@SerializedName("upnpresponseport")
@Expose
private Integer upnpresponseport; private Integer upnpresponseport;
@SerializedName("upnpdevicedb")
@Expose
private String upnpdevicedb; private String upnpdevicedb;
@SerializedName("veraaddress")
@Expose
private IpList veraaddress; private IpList veraaddress;
@SerializedName("harmonyaddress")
@Expose
private IpList harmonyaddress; private IpList harmonyaddress;
@SerializedName("buttonsleep")
@Expose
private Integer buttonsleep; private Integer buttonsleep;
@SerializedName("upnpstrict")
@Expose
private boolean upnpstrict; private boolean upnpstrict;
@SerializedName("traceupnp")
@Expose
private boolean traceupnp; private boolean traceupnp;
@SerializedName("nestuser")
@Expose
private String nestuser; private String nestuser;
@SerializedName("nestpwd")
@Expose
private String nestpwd; private String nestpwd;
@SerializedName("farenheit")
@Expose
private boolean farenheit;
@SerializedName("configfile")
@Expose
private String configfile;
@SerializedName("numberoflogmessages")
@Expose
private Integer numberoflogmessages;
@SerializedName("hueaddress")
@Expose
private IpList hueaddress;
@SerializedName("haladdress")
@Expose
private IpList haladdress;
@SerializedName("haltoken")
@Expose
private String haltoken;
@SerializedName("whitelist")
@Expose
private Map<String, WhitelistEntry> whitelist;
@SerializedName("myechourl")
@Expose
private String myechourl;
@SerializedName("webaddress")
@Expose
private String webaddress;
@SerializedName("mqttaddress")
@Expose
private IpList mqttaddress;
@SerializedName("hassaddress")
@Expose
private IpList hassaddress;
@SerializedName("domoticzaddress")
@Expose
private IpList domoticzaddress;
@SerializedName("somfyaddress")
@Expose
private IpList somfyaddress;
@SerializedName("hubversion")
@Expose
private String hubversion;
@SerializedName("securityData")
@Expose
private String securityData;
private boolean settingsChanged;
private boolean veraconfigured; private boolean veraconfigured;
private boolean harmonyconfigured; private boolean harmonyconfigured;
private boolean nestconfigured;
private boolean farenheit;
private String configfile;
private Integer numberoflogmessages;
private IpList hueaddress;
private boolean hueconfigured; private boolean hueconfigured;
private IpList haladdress; private boolean nestconfigured;
private String haltoken;
private boolean halconfigured; private boolean halconfigured;
private Map<String, WhitelistEntry> whitelist;
private boolean settingsChanged;
private String myechourl;
private String webaddress;
private IpList mqttaddress;
private boolean mqttconfigured; private boolean mqttconfigured;
private IpList hassaddress;
private boolean hassconfigured; private boolean hassconfigured;
private String hubversion;
private IpList domoticzaddress;
private boolean domoticzconfigured; private boolean domoticzconfigured;
private IpList somfyaddress;
private boolean somfyconfigured; private boolean somfyconfigured;
private boolean lifxconfigured; private boolean lifxconfigured;
private String securityData;
public BridgeSettingsDescriptor() { public BridgeSettingsDescriptor() {
super(); super();
@@ -226,8 +273,8 @@ public class BridgeSettingsDescriptor {
public Map<String, WhitelistEntry> getWhitelist() { public Map<String, WhitelistEntry> getWhitelist() {
return whitelist; return whitelist;
} }
public void setWhitelist(Map<String, WhitelistEntry> whitelist) { protected void removeWhitelist() {
this.whitelist = whitelist; whitelist = null;
} }
public boolean isSettingsChanged() { public boolean isSettingsChanged() {
return settingsChanged; return settingsChanged;
@@ -377,80 +424,4 @@ public class BridgeSettingsDescriptor {
public Boolean isValidLifx() { public Boolean isValidLifx() {
return this.isLifxconfigured(); return this.isLifxconfigured();
} }
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
String validUser = null;
boolean found = false;
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
&& !aUser.equalsIgnoreCase("")) {
if (whitelist != null) {
Set<String> theUserIds = whitelist.keySet();
Iterator<String> userIterator = theUserIds.iterator();
while (userIterator.hasNext()) {
validUser = userIterator.next();
if (validUser.equals(aUser))
found = true;
}
}
}
if(!found && !strict) {
newWhitelistUser(aUser, userDescription);
found = true;
}
if (!found) {
return HueErrorResponse.createResponse("1", "/api/" + aUser, "unauthorized user", null, null, null).getTheErrors();
}
return null;
}
public void newWhitelistUser(String aUser, String userDescription) {
if (whitelist == null) {
whitelist = new HashMap<>();
}
if(userDescription == null)
userDescription = "auto insert user";
whitelist.put(aUser, WhitelistEntry.createEntry(userDescription));
setSettingsChanged(true);
}
public String createWhitelistUser(String userDescription) {
String aUser = getNewUserID();
newWhitelistUser(aUser, userDescription);
return aUser;
}
private String getNewUserID() {
UUID uid = UUID.randomUUID();
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
String newUser = "";
while (st.hasMoreTokens()) {
newUser = newUser + st.nextToken();
}
return newUser;
}
public String getInternalTestUser() {
return DEFAULT_INTERNAL_USER;
}
public void setupInternalTestUser() {
boolean found = false;
if(whitelist != null) {
for (String key : whitelist.keySet()) {
if(key.equals(DEFAULT_INTERNAL_USER)) {
found = true;
break;
}
}
}
if(!found) {
newWhitelistUser(DEFAULT_INTERNAL_USER, DEFAULT_USER_DESCRIPTION);
}
}
} }

View File

@@ -102,6 +102,9 @@ public class HABridge {
} }
} }
} }
bridgeSettings.getBridgeSecurity().removeTestUsers();
if(bridgeSettings.getBridgeSecurity().isSettingsChanged())
bridgeSettings.updateConfigFile();
log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting...."); log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting....");
System.exit(0); System.exit(0);
} }

View File

@@ -2,7 +2,6 @@ package com.bwssystems.HABridge;
public class SecurityInfo { public class SecurityInfo {
private boolean useLinkButton; private boolean useLinkButton;
private String execGarden;
private boolean secureHueApi; private boolean secureHueApi;
private boolean isSecure; private boolean isSecure;
@@ -12,12 +11,6 @@ public class SecurityInfo {
public void setUseLinkButton(boolean useLinkButton) { public void setUseLinkButton(boolean useLinkButton) {
this.useLinkButton = useLinkButton; this.useLinkButton = useLinkButton;
} }
public String getExecGarden() {
return execGarden;
}
public void setExecGarden(String execGarden) {
this.execGarden = execGarden;
}
public boolean isSecureHueApi() { public boolean isSecureHueApi() {
return secureHueApi; return secureHueApi;
} }

View File

@@ -78,14 +78,6 @@ public class SystemControl {
return "{\"version\":\"" + version.getVersion() + "\",\"isSecure\":" + bridgeSettings.getBridgeSecurity().isSecure() + "}"; return "{\"version\":\"" + version.getVersion() + "\",\"isSecure\":" + bridgeSettings.getBridgeSecurity().isSecure() + "}";
}); });
// http://ip_address:port/system/habridge/testuser gets the valid test user for calling the api
get (SYSTEM_CONTEXT + "/habridge/testuser", (request, response) -> {
log.debug("Get HA Bridge testuser: " + bridgeSettings.getBridgeSettingsDescriptor().getInternalTestUser());
response.status(HttpStatus.SC_OK);
response.type("application/json");
return "{\"user\":\"" + bridgeSettings.getBridgeSettingsDescriptor().getInternalTestUser() + "\"}";
});
// http://ip_address:port/system/logmsgs gets the log messages for the bridge // http://ip_address:port/system/logmsgs gets the log messages for the bridge
get (SYSTEM_CONTEXT + "/logmsgs", (request, response) -> { get (SYSTEM_CONTEXT + "/logmsgs", (request, response) -> {
log.debug("Get logmsgs."); log.debug("Get logmsgs.");
@@ -283,8 +275,6 @@ public class SystemControl {
post(SYSTEM_CONTEXT + "/changesecurityinfo", (request, response) -> { post(SYSTEM_CONTEXT + "/changesecurityinfo", (request, response) -> {
log.debug("changesecurityinfo...."); log.debug("changesecurityinfo....");
SecurityInfo theInfo = new Gson().fromJson(request.body(), SecurityInfo.class); SecurityInfo theInfo = new Gson().fromJson(request.body(), SecurityInfo.class);
if(theInfo.getExecGarden() != null)
bridgeSettings.getBridgeSecurity().setExecGarden(theInfo.getExecGarden());
bridgeSettings.getBridgeSecurity().setUseLinkButton(theInfo.isUseLinkButton()); bridgeSettings.getBridgeSecurity().setUseLinkButton(theInfo.isUseLinkButton());
bridgeSettings.getBridgeSecurity().setSecureHueApi(theInfo.isSecureHueApi()); bridgeSettings.getBridgeSecurity().setSecureHueApi(theInfo.isSecureHueApi());
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor()); bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());

View File

@@ -595,9 +595,9 @@ public class HueMulator {
private String basicListHandler(String type, String userId, String requestIp) { private String basicListHandler(String type, String userId, String requestIp) {
log.debug("hue " + type + " list requested: " + userId + " from " + requestIp); log.debug("hue " + type + " list requested: " + userId + " from " + requestIp);
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors != null) { if (theErrors != null) {
if(bridgeSettings.isSettingsChanged()) if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
bridgeSettingMaster.updateConfigFile(); bridgeSettingMaster.updateConfigFile();
return aGsonHandler.toJson(theErrors); return aGsonHandler.toJson(theErrors);
@@ -609,9 +609,9 @@ public class HueMulator {
log.debug("hue group list requested: " + userId + " from " + requestIp); log.debug("hue group list requested: " + userId + " from " + requestIp);
HueError[] theErrors = null; HueError[] theErrors = null;
Map<String, GroupResponse> groupResponseMap = null; Map<String, GroupResponse> groupResponseMap = null;
theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors == null) { if (theErrors == null) {
if(bridgeSettings.isSettingsChanged()) if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
bridgeSettingMaster.updateConfigFile(); bridgeSettingMaster.updateConfigFile();
groupResponseMap = new HashMap<String, GroupResponse>(); groupResponseMap = new HashMap<String, GroupResponse>();
@@ -626,9 +626,9 @@ public class HueMulator {
private Object groupsIdHandler(String groupId, String userId, String requestIp) { private Object groupsIdHandler(String groupId, String userId, String requestIp) {
log.debug("hue group id: <" + groupId + "> requested: " + userId + " from " + requestIp); log.debug("hue group id: <" + groupId + "> requested: " + userId + " from " + requestIp);
HueError[] theErrors = null; HueError[] theErrors = null;
theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors == null) { if (theErrors == null) {
if(bridgeSettings.isSettingsChanged()) if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
bridgeSettingMaster.updateConfigFile(); bridgeSettingMaster.updateConfigFile();
if (groupId.equalsIgnoreCase("0")) { if (groupId.equalsIgnoreCase("0")) {
@@ -651,9 +651,9 @@ public class HueMulator {
if (bridgeSettings.isTraceupnp()) if (bridgeSettings.isTraceupnp())
log.info("Traceupnp: hue lights list requested: " + userId + " from " + requestIp); log.info("Traceupnp: hue lights list requested: " + userId + " from " + requestIp);
log.debug("hue lights list requested: " + userId + " from " + requestIp); log.debug("hue lights list requested: " + userId + " from " + requestIp);
theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors == null) { if (theErrors == null) {
if(bridgeSettings.isSettingsChanged()) if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
bridgeSettingMaster.updateConfigFile(); bridgeSettingMaster.updateConfigFile();
List<DeviceDescriptor> deviceList = repository.findAllByRequester(requestIp); List<DeviceDescriptor> deviceList = repository.findAllByRequester(requestIp);
@@ -727,13 +727,13 @@ public class HueMulator {
aDeviceType = "<not given>"; aDeviceType = "<not given>";
if (newUser == null) { if (newUser == null) {
newUser = bridgeSettings.createWhitelistUser(aDeviceType); newUser = bridgeSettingMaster.getBridgeSecurity().createWhitelistUser(aDeviceType);
} }
else { else {
bridgeSettings.validateWhitelistUser(newUser, aDeviceType, false); bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(newUser, aDeviceType, false);
} }
if(bridgeSettings.isSettingsChanged()) if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
bridgeSettingMaster.updateConfigFile(); bridgeSettingMaster.updateConfigFile();
if (bridgeSettings.isTraceupnp()) if (bridgeSettings.isTraceupnp())
@@ -749,7 +749,7 @@ public class HueMulator {
if (bridgeSettings.isTraceupnp()) if (bridgeSettings.isTraceupnp())
log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + ipAddress); log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + ipAddress);
log.debug("hue api config requested: " + userId + " from " + ipAddress); log.debug("hue api config requested: " + userId + " from " + ipAddress);
if (bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) { if (bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) {
log.debug("hue api config requested, No User supplied, returning public config"); log.debug("hue api config requested, No User supplied, returning public config");
HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue", HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue",
bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion()); bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion());
@@ -765,7 +765,7 @@ public class HueMulator {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Object getFullState(String userId, String ipAddress) { private Object getFullState(String userId, String ipAddress) {
log.debug("hue api full state requested: " + userId + " from " + ipAddress); log.debug("hue api full state requested: " + userId + " from " + ipAddress);
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors != null) if (theErrors != null)
return theErrors; return theErrors;
@@ -779,7 +779,7 @@ public class HueMulator {
private Object getLight(String userId, String lightId, String ipAddress) { private Object getLight(String userId, String lightId, String ipAddress) {
log.debug("hue light requested: " + lightId + " for user: " + userId + " from " + ipAddress); log.debug("hue light requested: " + lightId + " for user: " + userId + " from " + ipAddress);
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors != null) if (theErrors != null)
return theErrors; return theErrors;
@@ -823,7 +823,7 @@ public class HueMulator {
Integer targetBri = null; Integer targetBri = null;
Integer targetBriInc = null; Integer targetBriInc = null;
log.debug("Update state requested: " + userId + " from " + ipAddress + " body: " + body); log.debug("Update state requested: " + userId + " from " + ipAddress + " body: " + body);
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors != null) if (theErrors != null)
return aGsonHandler.toJson(theErrors); return aGsonHandler.toJson(theErrors);
try { try {
@@ -873,7 +873,7 @@ public class HueMulator {
aMultiUtil.setDelayDefault(bridgeSettings.getButtonsleep()); aMultiUtil.setDelayDefault(bridgeSettings.getButtonsleep());
aMultiUtil.setSetCount(1); aMultiUtil.setSetCount(1);
log.debug("hue state change requested: " + userId + " from " + ipAddress + " body: " + body); log.debug("hue state change requested: " + userId + " from " + ipAddress + " body: " + body);
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()); HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
if (theErrors != null) if (theErrors != null)
return aGsonHandler.toJson(theErrors); return aGsonHandler.toJson(theErrors);
try { try {
@@ -983,6 +983,9 @@ public class HueMulator {
else else
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault()); aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, state.getBri(), targetBri, targetBriInc, device, body); 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();
}
} }
} }
} }

View File

@@ -16,7 +16,7 @@ import com.bwssystems.HABridge.hue.TimeDecode;
public class CommandHome implements Home { public class CommandHome implements Home {
private static final Logger log = LoggerFactory.getLogger(CommandHome.class); private static final Logger log = LoggerFactory.getLogger(CommandHome.class);
private String execGarden;; private BridgeSettings theSettings;
public CommandHome(BridgeSettings bridgeSettings) { public CommandHome(BridgeSettings bridgeSettings) {
super(); super();
@@ -25,7 +25,7 @@ public class CommandHome implements Home {
@Override @Override
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int itensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) { 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 responseString = null;
String intermediate; String intermediate;
if (anItem.getItem().getAsString().contains("exec://")) if (anItem.getItem().getAsString().contains("exec://"))
@@ -35,8 +35,9 @@ public class CommandHome implements Home {
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, itensity, targetBri, targetBriInc, false); intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, itensity, targetBri, targetBriInc, false);
intermediate = DeviceDataDecode.replaceDeviceData(intermediate, device); intermediate = DeviceDataDecode.replaceDeviceData(intermediate, device);
intermediate = TimeDecode.replaceTimeValue(intermediate); intermediate = TimeDecode.replaceTimeValue(intermediate);
if(execGarden != null) { String execGarden = theSettings.getBridgeSecurity().getExecGarden();
if(System.getProperty("os.name").toLowerCase().indexOf("win") > 0) if(execGarden != null && !execGarden.trim().isEmpty()) {
if(System.getProperty("os.name").toLowerCase().indexOf("win") >= 0)
intermediate = execGarden + "\\" + intermediate; intermediate = execGarden + "\\" + intermediate;
else else
intermediate = execGarden + "/" + intermediate; intermediate = execGarden + "/" + intermediate;
@@ -57,7 +58,7 @@ public class CommandHome implements Home {
Process p = Runtime.getRuntime().exec(anItem); Process p = Runtime.getRuntime().exec(anItem);
log.debug("Process running: " + p.isAlive()); log.debug("Process running: " + p.isAlive());
} catch (IOException e) { } 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 responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Error on calling out to device\", \"parameter\": \"/lights/" + lightId + "\",\"description\": \"Error on calling out to device\", \"parameter\": \"/lights/" + lightId
+ "state\"}}]"; + "state\"}}]";
@@ -75,7 +76,7 @@ public class CommandHome implements Home {
@Override @Override
public Home createHome(BridgeSettings bridgeSettings) { public Home createHome(BridgeSettings bridgeSettings) {
log.info("Command Home for system program execution created."); log.info("Command Home for system program execution created.");
this.execGarden = bridgeSettings.getBridgeSecurity().getExecGarden(); this.theSettings = bridgeSettings;
return this; return this;
} }

View File

@@ -54,13 +54,6 @@ legend.form-label {
font-size: 8pt; font-size: 8pt;
} }
.password-count {
float: right;
position: relative;
bottom: 24px;
right: 10px;
}
.msg-block { .msg-block {
margin-top:5px; margin-top:5px;
} }

View File

@@ -41,7 +41,6 @@
<li class="dropdown"> <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> <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"> <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/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> <li><a href="https://github.com/bwssytems/ha-bridge/wiki/HA-Bridge-FAQs" target="_blank">FAQ</a></li>
</ul> </ul>
@@ -64,6 +63,7 @@
</li> </li>
</ul> </ul>
</li> </li>
<li><a href="#!/login">Login/Logout</a></li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -84,7 +84,6 @@ app.run( async function ($rootScope, $location, Auth, bridgeService) {
Auth.init(); Auth.init();
if(Auth.isLoggedIn()) { if(Auth.isLoggedIn()) {
bridgeService.loadBridgeSettings(); bridgeService.loadBridgeSettings();
bridgeService.getTestUser();
bridgeService.getSecurityInfo(); bridgeService.getSecurityInfo();
bridgeService.viewMapTypes(); bridgeService.viewMapTypes();
$location.path("/"); $location.path("/");
@@ -94,13 +93,19 @@ app.run( async function ($rootScope, $location, Auth, bridgeService) {
} }
}); });
$rootScope.$on('securityError', function(event, data) {
Auth.logout();
event.preventDefault();
$location.path("/login");
});
$rootScope.$on('securityReinit', function(event, data) {
event.preventDefault();
Auth.logout();
$location.path("/login");
});
$rootScope.$on('$routeChangeStart', function (event, next) { $rootScope.$on('$routeChangeStart', function (event, next) {
if(Auth.isLoggedIn()) {
bridgeService.loadBridgeSettings();
bridgeService.getTestUser();
bridgeService.getSecurityInfo();
bridgeService.viewMapTypes();
}
if (!Auth.checkPermissionForView(next)){ if (!Auth.checkPermissionForView(next)){
event.preventDefault(); event.preventDefault();
$location.path("/login"); $location.path("/login");
@@ -185,6 +190,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.devices = response.data; self.state.devices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayError("Cannot get devices from habridge: ", error); self.displayError("Cannot get devices from habridge: ", error);
} }
); );
@@ -196,6 +204,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewDevices(); self.viewDevices();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayError("Cannot renumber devices from habridge: ", error); self.displayError("Cannot renumber devices from habridge: ", error);
} }
); );
@@ -228,22 +239,45 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
}; };
this.getTestUser = function () { this.getTestUser = function () {
return $http.get(this.state.systemsbase + "/habridge/testuser").then( if(self.state.testuser === undefined || self.state.testuser === "") {
return $http.put(this.state.systemsbase + "/presslinkbutton").then(
function (response) { function (response) {
self.state.testuser = response.data.user; self.getAUser();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Cannot get testuser: ", error); self.displayWarn("Cannot get testuser: ", error);
} }
); );
}
};
this.getAUser = function () {
return $http.post(this.state.huebase, "{\"devicetype\":\"test_ha_bridge\"}").then(
function (response) {
self.state.testuser = response.data[0].success.username;
},
function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Cannot get a user: ", error);
}
);
}; };
this.getSecurityInfo = function () { this.getSecurityInfo = function () {
return $http.get(this.state.systemsbase + "/securityinfo").then( return $http.get(this.state.systemsbase + "/securityinfo").then(
function (response) { function (response) {
self.state.securityInfo = response.data; self.state.securityInfo = response.data;
self.getTestUser();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Cannot get security info: ", error); self.displayWarn("Cannot get security info: ", error);
} }
); );
@@ -262,6 +296,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displaySuccess("Updated security settings.") self.displaySuccess("Updated security settings.")
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Update ecurity settings Error: ", error); self.displayWarn("Update ecurity settings Error: ", error);
} }
); );
@@ -289,6 +326,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displaySuccess("Password updated") self.displaySuccess("Password updated")
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Update password Error: ", error); self.displayWarn("Update password Error: ", error);
} }
); );
@@ -310,6 +350,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
} }
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("User add Error: ", error); self.displayWarn("User add Error: ", error);
} }
); );
@@ -326,6 +369,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displaySuccess("User deleted") self.displaySuccess("User deleted")
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("User add Error: ", error); self.displayWarn("User add Error: ", error);
} }
); );
@@ -337,6 +383,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displayTimer("Link your device", 30000); self.displayTimer("Link your device", 30000);
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Cannot get security info: ", error); self.displayWarn("Cannot get security info: ", error);
} }
); );
@@ -468,6 +517,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.updateShowLifx(); self.updateShowLifx();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Load Bridge Settings Error: ", error); self.displayWarn("Load Bridge Settings Error: ", error);
} }
); );
@@ -479,6 +531,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.backups = response.data; self.state.backups = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Backups Error: ", error); self.displayWarn("Get Backups Error: ", error);
} }
); );
@@ -490,6 +545,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.configs = response.data; self.state.configs = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Configs Error: ", error); self.displayWarn("Get Configs Error: ", error);
} }
); );
@@ -501,6 +559,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.logMsgs = response.data; self.state.logMsgs = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get log messages Error: ", error); self.displayWarn("Get log messages Error: ", error);
} }
); );
@@ -512,6 +573,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.loggerInfo = response.data; self.state.loggerInfo = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get logger info Error: ", error); self.displayWarn("Get logger info Error: ", error);
} }
); );
@@ -525,6 +589,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.nestitems = response.data; self.state.nestitems = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Nest Items Error: ", error); self.displayWarn("Get Nest Items Error: ", error);
} }
); );
@@ -538,6 +605,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.huedevices = response.data; self.state.huedevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Hue Items Error: ", error); self.displayWarn("Get Hue Items Error: ", error);
} }
); );
@@ -551,6 +621,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.veradevices = response.data; self.state.veradevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Vera Devices Error: ", error); self.displayWarn("Get Vera Devices Error: ", error);
} }
); );
@@ -564,6 +637,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.verascenes = response.data; self.state.verascenes = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Vera Scenes Error: ", error); self.displayWarn("Get Vera Scenes Error: ", error);
} }
); );
@@ -577,6 +653,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.harmonyactivities = response.data; self.state.harmonyactivities = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Harmony Activities Error: ", error); self.displayWarn("Get Harmony Activities Error: ", error);
} }
); );
@@ -590,6 +669,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.harmonydevices = response.data; self.state.harmonydevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Harmony Devices Error: ", error); self.displayWarn("Get Harmony Devices Error: ", error);
} }
); );
@@ -603,6 +685,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.haldevices = response.data; self.state.haldevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Hal Devices Error: ", error); self.displayWarn("Get Hal Devices Error: ", error);
} }
); );
@@ -616,6 +701,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.mqttbrokers = response.data; self.state.mqttbrokers = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get MQTT Devices Error: ", error); self.displayWarn("Get MQTT Devices Error: ", error);
} }
); );
@@ -629,6 +717,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.hassdevices = response.data; self.state.hassdevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Hass Devices Error: ", error); self.displayWarn("Get Hass Devices Error: ", error);
} }
); );
@@ -642,6 +733,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.domoticzdevices = response.data; self.state.domoticzdevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Domoticz Devices Error: ", error); self.displayWarn("Get Domoticz Devices Error: ", error);
} }
); );
@@ -655,6 +749,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.somfydevices = response.data; self.state.somfydevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Somfy Devices Error: ", error); self.displayWarn("Get Somfy Devices Error: ", error);
} }
); );
@@ -669,6 +766,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.lifxdevices = response.data; self.state.lifxdevices = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get Lifx Devices Error: ", error); self.displayWarn("Get Lifx Devices Error: ", error);
} }
); );
@@ -741,6 +841,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.state.mapTypes = response.data; self.state.mapTypes = response.data;
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Get mapTypes Error: ", error); self.displayWarn("Get mapTypes Error: ", error);
} }
); );
@@ -764,6 +867,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displaySuccess("Updated " + logComponents.length + " loggers for log levels.") self.displaySuccess("Updated " + logComponents.length + " loggers for log levels.")
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Update Log components Error: ", error); self.displayWarn("Update Log components Error: ", error);
} }
); );
@@ -792,6 +898,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displaySuccess("Bulk device add successful."); self.displaySuccess("Bulk device add successful.");
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Bulk Add new Device Error: ", error); self.displayWarn("Bulk Add new Device Error: ", error);
} }
); );
@@ -810,6 +919,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
function (response) { function (response) {
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Edit Device Error: ", error); self.displayWarn("Edit Device Error: ", error);
} }
); );
@@ -820,6 +932,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
function (response) { function (response) {
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Add new Device Error: ", error); self.displayWarn("Add new Device Error: ", error);
} }
); );
@@ -834,6 +949,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewBackups(); self.viewBackups();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Backup Device Db Error: ", error); self.displayWarn("Backup Device Db Error: ", error);
} }
); );
@@ -848,6 +966,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewDevices(); self.viewDevices();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Backup Db Restore Error: ", error); self.displayWarn("Backup Db Restore Error: ", error);
} }
); );
@@ -861,6 +982,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewBackups(); self.viewBackups();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Delete Backup Db File Error:", error); self.displayWarn("Delete Backup Db File Error:", error);
} }
); );
@@ -870,10 +994,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
return $http.get(this.state.bridgelocation + "/description.xml").then( return $http.get(this.state.bridgelocation + "/description.xml").then(
function (response) { function (response) {
ngToast.dismiss(self.state.myToastMsg); ngToast.dismiss(self.state.myToastMsg);
self.viewConfigs();
self.state.myToastMsg = null; self.state.myToastMsg = null;
self.state.isInControl = false; self.state.isInControl = false;
window.location.reload(); $rootScope.$broadcast('securityReinit', 'done');
}, },
function (error) { function (error) {
setTimeout(function(){ setTimeout(function(){
@@ -891,6 +1014,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displayError("HABridge is now stopped. Restart must occur from the server.", null); self.displayError("HABridge is now stopped. Restart must occur from the server.", null);
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayError("HABRidge Stop Error: ", error); self.displayError("HABRidge Stop Error: ", error);
} }
); );
@@ -910,6 +1036,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
}, 2000); }, 2000);
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("HABRidge Reinit Error: ", error); self.displayWarn("HABRidge Reinit Error: ", error);
} }
); );
@@ -921,6 +1050,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.reinit(); self.reinit();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Save Settings Error: ", error); self.displayWarn("Save Settings Error: ", error);
} }
); );
@@ -935,6 +1067,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewConfigs(); self.viewConfigs();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Backup Settings Error: ", error); self.displayWarn("Backup Settings Error: ", error);
} }
); );
@@ -950,6 +1085,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewDevices(); self.viewDevices();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Backup Settings Restore Error: ", error); self.displayWarn("Backup Settings Restore Error: ", error);
} }
); );
@@ -963,6 +1101,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewConfigs(); self.viewConfigs();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Delete Backup Settings File Error: ", error); self.displayWarn("Delete Backup Settings File Error: ", error);
} }
); );
@@ -974,6 +1115,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.viewDevices(); self.viewDevices();
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Delete Device Error: ", error); self.displayWarn("Delete Device Error: ", error);
} }
); );
@@ -1015,6 +1159,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
self.displaySuccess("Request Executed: " + msgDescription); self.displaySuccess("Request Executed: " + msgDescription);
}, },
function (error) { function (error) {
if (error.status === 401)
$rootScope.$broadcast('securityReinit', 'done');
else
self.displayWarn("Request Error, Pleae look in your habridge log: ", error); self.displayWarn("Request Error, Pleae look in your habridge log: ", error);
} }
); );
@@ -1298,6 +1445,17 @@ app.controller ('SystemController', function ($scope, $location, bridgeService,
}; };
}); });
app.directive('autofocus', ['$timeout', function($timeout) {
return {
restrict: 'A',
link : function($scope, $element) {
$timeout(function() {
$element[0].focus();
});
}
}
}]);
app.directive('nuCheck', [function () { app.directive('nuCheck', [function () {
return { return {
require: 'ngModel', require: 'ngModel',
@@ -2905,7 +3063,6 @@ app.controller('SomfyController', function ($scope, $location, bridgeService, ng
}); });
app.controller('EditController', function ($scope, $location, bridgeService) { app.controller('EditController', function ($scope, $location, bridgeService) {
bridgeService.viewMapTypes();
$scope.bridge = bridgeService.state; $scope.bridge = bridgeService.state;
$scope.device = bridgeService.state.device; $scope.device = bridgeService.state.device;
$scope.onDevices = null; $scope.onDevices = null;
@@ -3213,6 +3370,7 @@ app.filter('configuredSomfyDevices', function (bridgeService) {
app.controller('LoginController', function ($scope, $location, Auth) { app.controller('LoginController', function ($scope, $location, Auth) {
$scope.failed = false; $scope.failed = false;
$scope.loggedIn = Auth.isLoggedIn();
$scope.login = function(username, password) { $scope.login = function(username, password) {
Auth.login(username, password) Auth.login(username, password)
.then(function() { .then(function() {
@@ -3224,6 +3382,9 @@ app.controller('LoginController', function ($scope, $location, Auth) {
$scope.logout = function() { $scope.logout = function() {
Auth.logout(); Auth.logout();
$scope.loggedIn = Auth.isLoggedIn();
bridgeService.displaySuccess("User Logged Out");
$location.path("/login");
}; };
}); });
@@ -3288,7 +3449,6 @@ app.factory('Auth', function($resource, $rootScope, $sessionStorage, $http, $bas
delete $sessionStorage.user; delete $sessionStorage.user;
delete $rootScope.user; delete $rootScope.user;
delete bridgeService.state.loggedInUser; delete bridgeService.state.loggedInUser;
bridgeService.displaySuccess("User Logged Out");
}; };

View File

@@ -3,25 +3,27 @@
<h2 class="panel-title">Login</h2> <h2 class="panel-title">Login</h2>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="form-container"> <div ng-if="!loggedIn" class="form-container">
<form name="loginForm" role="form"> <form name="loginForm" role="form" ng-submit="login(username, password)">
<legend class="form-label">Enter Credentials</legend> <legend class="form-label">Enter Credentials</legend>
<div class="form-group"> <div class="form-group">
<label>User</label> <input id="username" name="username" <label>User</label> <input id="username" name="username"
class="form-control" type="text" ng-model="username" class="form-control" type="text" ng-model="username"
placeholder="someone" /> placeholder="someone" autofocus/>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Password</label> <input id="password" name="password" <label>Password</label> <input id="password" name="password"
class="form-control" type="password" ng-model="password" /> class="form-control" type="password" ng-model="password" />
</div> </div>
<div class="form-group"> <div class="form-group">
<button type="button" class="btn btn-success" ng-click="login(username, password)">Submit</button> <button type="submit" class="btn btn-success" value="Submit">Submit</button>
<button type="button" class="btn btn-danger" ng-click="logout()">Logout</button>
</div> </div>
</form> </form>
</div> </div>
<div ng-if="loggedIn">
<button type="button" class="btn btn-danger" ng-click="logout()">Logout</button>
</div>
</div> </div>
</div> </div>

View File

@@ -6,19 +6,13 @@
<label>Use Link Button</label> <label>Use Link Button</label>
<input type="checkbox" <input type="checkbox"
ng-model="useLinkButton" ng-true-value=true ng-model="useLinkButton" ng-true-value=true
ng-false-value=false> {{useLinkButton}} ng-false-value=false /> {{useLinkButton}}
</div> </div>
<div class="form-group"> <div class="form-group">
<label>Use username/password for HUE Api</label> <label>Use username/password for HUE Api</label>
<input type="checkbox" <input type="checkbox"
ng-model="secureHueApi" ng-true-value=true ng-model="secureHueApi" ng-true-value=true
ng-false-value=false> {{secureHueApi}} ng-false-value=false /> {{secureHueApi}}
</div>
<div class="form-group">
<label>Secure Folder for scripts/executables</label>
<input id="exec-garden" class="form-control"
type="text" ng-model="execGarden"
placeholder="/home/pi/protectedscripts">
</div> </div>
<div class="form-group"> <div class="form-group">
<button type="button" class="btn btn-primary" ng-click="setSecurityInfo()">Update</button> <button type="button" class="btn btn-primary" ng-click="setSecurityInfo()">Update</button>
@@ -27,7 +21,7 @@
<label>Add/Delete User</label> <label>Add/Delete User</label>
<input id="new-user" name="new-user" class="form-control" <input id="new-user" name="new-user" class="form-control"
type="text" ng-model="newUser" type="text" ng-model="newUser"
placeholder="someone" nu-check="new-user"> placeholder="someone" nu-check="new-user" />
</div> </div>
<div class="form-group"> <div class="form-group">
<button type="button" class="btn btn-danger" ng-click="delUser(newUser)">Delete</button> <button type="button" class="btn btn-danger" ng-click="delUser(newUser)">Delete</button>
@@ -50,7 +44,7 @@
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<button type="button" class="btn btn-success" ng-click="dismissDialog()">Dismiss</button> <button type="button" class="btn btn-success" ng-click="dismissDialog()" autofocus>Dismiss</button>
</div> </div>
</form> </form>

View File

@@ -48,16 +48,9 @@
<button ng-disabled="bridge.isInControl" <button ng-disabled="bridge.isInControl"
class="btn btn-success" type="submit" ng-click="saveSettings()">Save</button> class="btn btn-success" type="submit" ng-click="saveSettings()">Save</button>
<button ng-disabled="bridge.isInControl" class="btn btn-warning" <button ng-disabled="bridge.isInControl" class="btn btn-warning"
type="submit" ng-click="bridgeReinit()">Bridge type="submit" ng-click="bridgeReinit()">Bridge Reinitialize</button>
Reinitialize</button>
<button ng-disabled="bridge.isInControl" class="btn btn-danger" <button ng-disabled="bridge.isInControl" class="btn btn-danger"
type="submit" ng-click="bridgeStop()">Bridge Stop</button> 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" <button class="btn btn-warning"
type="submit" ng-click="changeSeuritySettings()">Update Security Settings</button> type="submit" ng-click="changeSeuritySettings()">Update Security Settings</button>
</p> </p>