Continue with security impl, starting to gell....

This commit is contained in:
Admin
2017-03-29 16:41:59 -05:00
parent 7442b0d0ca
commit ba621fcb85
6 changed files with 206 additions and 33 deletions

View File

@@ -61,10 +61,12 @@ public class SystemControl extends AuthFramework {
log.info("System control service started....");
before(SYSTEM_CONTEXT + "/*", (request, response) -> {
if(bridgeSettings.getBridgeSecurity().isSecure()) {
String pathInfo = request.pathInfo();
if(pathInfo == null || !pathInfo.equals(SYSTEM_CONTEXT + "/login")) {
User authUser = getAuthenticatedUser(request);
if(authUser == null) {
response.redirect("/login", 301);
// halt(401, "You are not logged in....");
halt(401, "{\"message\":\"User not authenticated\"}");
}
}
}
});

View File

@@ -41,6 +41,7 @@
<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>
@@ -84,6 +85,8 @@
<script src="js/angular-scrollable-table.min.js"></script>
<script src="js/strength-meter.min.js"></script>
<script src="js/angular-base64.min.js"></script>
<script src="js/angular-resource.min.js"></script>
<script src="js/ngStorage.min.js"></script>
<script src="scripts/app.js"></script>
</body>
</html>

View File

@@ -0,0 +1,15 @@
/*
AngularJS v1.6.1
(c) 2010-2016 Google, Inc. http://angularjs.org
License: MIT
*/
(function(W,b){'use strict';function K(q,g){g=g||{};b.forEach(g,function(b,h){delete g[h]});for(var h in q)!q.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(g[h]=q[h]);return g}var B=b.$$minErr("$resource"),Q=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;b.module("ngResource",["ng"]).provider("$resource",function(){var q=/^https?:\/\/\[[^\]]*][^/]*/,g=this;this.defaults={stripTrailingSlashes:!0,cancellable:!1,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},
"delete":{method:"DELETE"}}};this.$get=["$http","$log","$q","$timeout",function(h,P,L,M){function C(b,e){this.template=b;this.defaults=p({},g.defaults,e);this.urlParams={}}function x(D,e,u,m){function c(a,d){var c={};d=p({},e,d);t(d,function(d,l){y(d)&&(d=d(a));var f;if(d&&d.charAt&&"@"===d.charAt(0)){f=a;var k=d.substr(1);if(null==k||""===k||"hasOwnProperty"===k||!Q.test("."+k))throw B("badmember",k);for(var k=k.split("."),e=0,g=k.length;e<g&&b.isDefined(f);e++){var h=k[e];f=null!==f?f[h]:void 0}}else f=
d;c[l]=f});return c}function R(a){return a.resource}function l(a){K(a||{},this)}var q=new C(D,m);u=p({},g.defaults.actions,u);l.prototype.toJSON=function(){var a=p({},this);delete a.$promise;delete a.$resolved;return a};t(u,function(a,d){var b=/^(POST|PUT|PATCH)$/i.test(a.method),e=a.timeout,g=N(a.cancellable)?a.cancellable:q.defaults.cancellable;e&&!S(e)&&(P.debug("ngResource:\n Only numeric values are allowed as `timeout`.\n Promises are not supported in $resource, because the same value would be used for multiple requests. If you are looking for a way to cancel requests, you should use the `cancellable` option."),
delete a.timeout,e=null);l[d]=function(f,k,m,D){function u(a){r.catch(E);z.resolve(a)}var G={},v,w,A;switch(arguments.length){case 4:A=D,w=m;case 3:case 2:if(y(k)){if(y(f)){w=f;A=k;break}w=k;A=m}else{G=f;v=k;w=m;break}case 1:y(f)?w=f:b?v=f:G=f;break;case 0:break;default:throw B("badargs",arguments.length);}var F=this instanceof l,n=F?v:a.isArray?[]:new l(v),s={},C=a.interceptor&&a.interceptor.response||R,x=a.interceptor&&a.interceptor.responseError||void 0,H=!!A,I=!!x,z,J;t(a,function(a,d){switch(d){default:s[d]=
T(a);case "params":case "isArray":case "interceptor":case "cancellable":}});!F&&g&&(z=L.defer(),s.timeout=z.promise,e&&(J=M(z.resolve,e)));b&&(s.data=v);q.setUrlParams(s,p({},c(v,a.params||{}),G),a.url);var r=h(s).then(function(f){var c=f.data;if(c){if(O(c)!==!!a.isArray)throw B("badcfg",d,a.isArray?"array":"object",O(c)?"array":"object",s.method,s.url);if(a.isArray)n.length=0,t(c,function(a){"object"===typeof a?n.push(new l(a)):n.push(a)});else{var b=n.$promise;K(c,n);n.$promise=b}}f.resource=n;
return f}),r=r["finally"](function(){n.$resolved=!0;!F&&g&&(n.$cancelRequest=E,M.cancel(J),z=J=s.timeout=null)}),r=r.then(function(a){var d=C(a);(w||E)(d,a.headers,a.status,a.statusText);return d},H||I?function(a){H&&A(a);return I?x(a):L.reject(a)}:void 0);H&&!I&&r.catch(E);return F?r:(n.$promise=r,n.$resolved=!1,g&&(n.$cancelRequest=u),n)};l.prototype["$"+d]=function(a,c,b){y(a)&&(b=c,c=a,a={});a=l[d].call(this,a,this,c,b);return a.$promise||a}});l.bind=function(a){a=p({},e,a);return x(D,a,u,m)};
return l}var E=b.noop,t=b.forEach,p=b.extend,T=b.copy,O=b.isArray,N=b.isDefined,y=b.isFunction,S=b.isNumber,U=b.$$encodeUriQuery,V=b.$$encodeUriSegment;C.prototype={setUrlParams:function(b,e,g){var m=this,c=g||m.template,h,l,p="",a=m.urlParams=Object.create(null);t(c.split(/\W/),function(d){if("hasOwnProperty"===d)throw B("badname");!/^\d+$/.test(d)&&d&&(new RegExp("(^|[^\\\\]):"+d+"(\\W|$)")).test(c)&&(a[d]={isQueryParamValue:(new RegExp("\\?.*=:"+d+"(?:\\W|$)")).test(c)})});c=c.replace(/\\:/g,":");
c=c.replace(q,function(a){p=a;return""});e=e||{};t(m.urlParams,function(a,b){h=e.hasOwnProperty(b)?e[b]:m.defaults[b];N(h)&&null!==h?(l=a.isQueryParamValue?U(h,!0):V(h),c=c.replace(new RegExp(":"+b+"(\\W|$)","g"),function(a,b){return l+b})):c=c.replace(new RegExp("(/?):"+b+"(\\W|$)","g"),function(a,b,d){return"/"===d.charAt(0)?d:b+d})});m.defaults.stripTrailingSlashes&&(c=c.replace(/\/+$/,"")||"/");c=c.replace(/\/\.(?=\w+($|\?))/,".");b.url=p+c.replace(/\/\\\./,"/.");t(e,function(a,c){m.urlParams[c]||
(b.params=b.params||{},b.params[c]=a)})}};return x}]})})(window,window.angular);
//# sourceMappingURL=angular-resource.min.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
/*! ngstorage 0.3.10 | Copyright (c) 2016 Gias Kay Lee | MIT License */!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["angular"],b):a.hasOwnProperty("angular")?b(a.angular):"object"==typeof exports&&(module.exports=b(require("angular")))}(this,function(a){"use strict";function b(a,b){var c;try{c=a[b]}catch(d){c=!1}if(c){var e="__"+Math.round(1e7*Math.random());try{a[b].setItem(e,e),a[b].removeItem(e,e)}catch(d){c=!1}}return c}function c(c){var d=b(window,c);return function(){var e="ngStorage-";this.setKeyPrefix=function(a){if("string"!=typeof a)throw new TypeError("[ngStorage] - "+c+"Provider.setKeyPrefix() expects a String.");e=a};var f=a.toJson,g=a.fromJson;this.setSerializer=function(a){if("function"!=typeof a)throw new TypeError("[ngStorage] - "+c+"Provider.setSerializer expects a function.");f=a},this.setDeserializer=function(a){if("function"!=typeof a)throw new TypeError("[ngStorage] - "+c+"Provider.setDeserializer expects a function.");g=a},this.supported=function(){return!!d},this.get=function(a){return d&&g(d.getItem(e+a))},this.set=function(a,b){return d&&d.setItem(e+a,f(b))},this.remove=function(a){d&&d.removeItem(e+a)},this.$get=["$rootScope","$window","$log","$timeout","$document",function(d,h,i,j,k){var l,m,n=e.length,o=b(h,c),p=o||(i.warn("This browser does not support Web Storage!"),{setItem:a.noop,getItem:a.noop,removeItem:a.noop}),q={$default:function(b){for(var c in b)a.isDefined(q[c])||(q[c]=a.copy(b[c]));return q.$sync(),q},$reset:function(a){for(var b in q)"$"===b[0]||delete q[b]&&p.removeItem(e+b);return q.$default(a)},$sync:function(){for(var a,b=0,c=p.length;c>b;b++)(a=p.key(b))&&e===a.slice(0,n)&&(q[a.slice(n)]=g(p.getItem(a)))},$apply:function(){var b;if(m=null,!a.equals(q,l)){b=a.copy(l),a.forEach(q,function(c,d){a.isDefined(c)&&"$"!==d[0]&&(p.setItem(e+d,f(c)),delete b[d])});for(var c in b)p.removeItem(e+c);l=a.copy(q)}},$supported:function(){return!!o}};return q.$sync(),l=a.copy(q),d.$watch(function(){m||(m=j(q.$apply,100,!1))}),h.addEventListener&&h.addEventListener("storage",function(b){if(b.key){var c=k[0];c.hasFocus&&c.hasFocus()||e!==b.key.slice(0,n)||(b.newValue?q[b.key.slice(n)]=g(b.newValue):delete q[b.key.slice(n)],l=a.copy(q),d.$apply())}}),h.addEventListener&&h.addEventListener("beforeunload",function(){q.$apply()}),q}]}}return a=a&&a.module?a:window.angular,a.module("ngStorage",[]).provider("$localStorage",c("localStorage")).provider("$sessionStorage",c("sessionStorage"))});

View File

@@ -1,73 +1,99 @@
var app = angular.module ('habridge', ['ngRoute', 'ngToast', 'rzModule', 'ngDialog', 'base64', 'scrollable-table']);
var app = angular.module ('habridge', ['ngRoute', 'ngToast', 'rzModule', 'ngDialog', 'base64', 'scrollable-table', 'ngResource', 'ngStorage']);
app.config (function ($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
$routeProvider.when ('/', {
templateUrl: 'views/configuration.html',
controller: 'ViewingController'
controller: 'ViewingController',
requiresAuthentication: true
}).when ('/system', {
templateUrl: 'views/system.html',
controller: 'SystemController'
controller: 'SystemController',
requiresAuthentication: true
}).when ('/logs', {
templateUrl: 'views/logs.html',
controller: 'LogsController'
controller: 'LogsController',
requiresAuthentication: true
}).when ('/editdevice', {
templateUrl: 'views/editdevice.html',
controller: 'EditController'
controller: 'EditController',
requiresAuthentication: true
}).when ('/veradevices', {
templateUrl: 'views/veradevice.html',
controller: 'VeraController'
controller: 'VeraController',
requiresAuthentication: true
}).when ('/verascenes', {
templateUrl: 'views/verascene.html',
controller: 'VeraController'
controller: 'VeraController',
requiresAuthentication: true
}).when ('/harmonydevices', {
templateUrl: 'views/harmonydevice.html',
controller: 'HarmonyController'
controller: 'HarmonyController',
requiresAuthentication: true
}).when ('/harmonyactivities', {
templateUrl: 'views/harmonyactivity.html',
controller: 'HarmonyController'
controller: 'HarmonyController',
requiresAuthentication: true
}).when ('/nest', {
templateUrl: 'views/nestactions.html',
controller: 'NestController'
controller: 'NestController',
requiresAuthentication: true
}).when ('/huedevices', {
templateUrl: 'views/huedevice.html',
controller: 'HueController'
controller: 'HueController',
requiresAuthentication: true
}).when ('/haldevices', {
templateUrl: 'views/haldevice.html',
controller: 'HalController'
controller: 'HalController',
requiresAuthentication: true
}).when ('/mqttmessages', {
templateUrl: 'views/mqttpublish.html',
controller: 'MQTTController'
controller: 'MQTTController',
requiresAuthentication: true
}).when ('/hassdevices', {
templateUrl: 'views/hassdevice.html',
controller: 'HassController'
controller: 'HassController',
requiresAuthentication: true
}).when ('/domoticzdevices', {
templateUrl: 'views/domoticzdevice.html',
controller: 'DomoticzController'
controller: 'DomoticzController',
requiresAuthentication: true
}).when('/somfydevices', {
templateUrl: 'views/somfydevice.html',
controller: 'SomfyController'
}).otherwise ({
controller: 'DomoticzController'
templateUrl: 'views/somfydevice.html',
controller: 'SomfyController',
requiresAuthentication: true
}).when ('/lifxdevices', {
templateUrl: 'views/lifxdevice.html',
controller: 'LifxController'
controller: 'LifxController',
requiresAuthentication: true
}).when ('/login', {
templateUrl: 'views/login.html',
controller: 'LoginController'
}).otherwise ({
templateUrl: 'views/configuration.html',
controller: 'ViewingController'
controller: 'ViewingController',
requiresAuthentication: true
})
});
app.run( function (bridgeService) {
bridgeService.loadBridgeSettings();
bridgeService.getHABridgeVersion();
bridgeService.getTestUser();
bridgeService.getSecurityInfo();
bridgeService.viewMapTypes();
app.run( function ($rootScope, $location, Auth, bridgeService) {
Auth.init();
$rootScope.$on('$routeChangeStart', function (event, next) {
if (!Auth.checkPermissionForView(next)){
event.preventDefault();
$location.path("/login");
}
});
if(Auth.isLoggedIn()) {
bridgeService.loadBridgeSettings();
bridgeService.getHABridgeVersion();
bridgeService.getTestUser();
bridgeService.getSecurityInfo();
bridgeService.viewMapTypes();
}
});
String.prototype.replaceAll = function (search, replace)
@@ -3137,14 +3163,132 @@ app.filter('configuredSomfyDevices', function (bridgeService) {
}
});
app.controller('LoginController', function ($scope, bridgeService) {
$scope.bridge = bridgeService.state;
app.controller('LoginController', function ($scope, $location, Auth) {
$scope.failed = false;
$scope.login = function(username, password) {
bridgeService.validateUser(username,password);
Auth.login(username, password)
.then(function() {
$location.path("/");
}, function() {
$scope.failed = true;
});
};
});
app.controller('VersionController', function ($scope, bridgeService) {
$scope.bridge = bridgeService.state;
});
app.directive('permission', ['Auth', function(Auth) {
return {
restrict: 'A',
scope: {
permission: '='
},
link: function (scope, elem, attrs) {
scope.$watch(Auth.isLoggedIn, function() {
if (Auth.userHasPermission(scope.permission)) {
elem.show();
} else {
elem.hide();
}
});
}
}
}]);
app.factory('Auth', function($resource, $rootScope, $sessionStorage, $http, $base64, bridgeService){
var auth = {};
/**
* Saves the current user in the root scope
* Call this in the app run() method
*/
auth.init = function(){
if (auth.isLoggedIn()){
$rootScope.user = currentUser();
}
};
auth.login = function(username, password){
var newUserInfo = {};
newUserInfo = {
username: username,
password: password
};
var theEncodedPayload = $base64.encode(angular.toJson(newUserInfo));
return $http.post(bridgeService.state.systemsbase + "/login", theEncodedPayload ).then(
function (response) {
var theResult = response.data;
$sessionStorage.user = theResult.user;
$rootScope.user = $sessionStorage.user;
bridgeService.loadBridgeSettings();
bridgeService.getHABridgeVersion();
bridgeService.getTestUser();
bridgeService.getSecurityInfo();
bridgeService.viewMapTypes();
}, function(error) {
bridgeService.displayWarn("Login Error: ", error);
});
};
auth.logout = function() {
delete $sessionStorage.user;
delete $rootScope.user;
};
auth.checkPermissionForView = function(view) {
if (!view.requiresAuthentication) {
return true;
}
return userHasPermissionForView(view);
};
var userHasPermissionForView = function(view){
if(!auth.isLoggedIn()){
return false;
}
if(!view.permissions || !view.permissions.length){
return true;
}
return auth.userHasPermission(view.permissions);
};
auth.userHasPermission = function(permissions){
if(!auth.isLoggedIn()){
return false;
}
var found = false;
angular.forEach(permissions, function(permission, index){
if ($sessionStorage.user.user_permissions.indexOf(permission) >= 0){
found = true;
return;
}
});
return found;
};
auth.currentUser = function(){
return $sessionStorage.user;
};
auth.isLoggedIn = function(){
return $sessionStorage.user != null;
};
return auth;
});