Skip to content
This repository was archived by the owner on May 14, 2025. It is now read-only.

Commit 392a9f4

Browse files
committed
gh-155 Make the Dashboard Role-aware
1 parent 67603cb commit 392a9f4

File tree

10 files changed

+114
-23
lines changed

10 files changed

+114
-23
lines changed

ui/app/index.html

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,27 @@
4040
</p>
4141
<p ng-if="user.authenticationEnabled && !user.isAuthenticated" class="navbar-text navbar-right">Not logged in</p>
4242
<ul class="nav navbar-nav navbar-right">
43-
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated"
43+
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated" roles="['ROLE_VIEW']"
4444
ng-class="{ active: $state.includes('home.apps') }">
45-
<a ui-sref="home.apps.tabs.appsList">Apps</a>
45+
<a ui-sref="home.apps.tabs.appsList">Apps</a>{{roles}}
4646
</li>
47-
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated"
47+
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated" roles="['ROLE_VIEW']"
4848
ng-class="{ active: $state.includes('home.runtime') }">
4949
<a ui-sref="home.runtime.tabs.runtimeAppsList">Runtime</a>
5050
</li>
51-
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated"
51+
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated" roles="['ROLE_VIEW']"
5252
ng-show="features.streamsEnabled" ng-class="{ active: $state.includes('home.streams') }">
5353
<a ui-sref="home.streams.tabs.definitions">Streams</a>
5454
</li>
55-
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated"
55+
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated" roles="['ROLE_VIEW']"
5656
ng-show="features.tasksEnabled" ng-class="{ active: $state.includes('home.tasks') }">
5757
<a ui-sref="home.tasks.tabs.definitions">Tasks</a>
5858
</li>
59-
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated"
59+
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated" roles="['ROLE_VIEW']"
6060
ng-show="features.tasksEnabled" ng-class="{ active: $state.includes('home.jobs') }">
6161
<a ui-sref="home.jobs.tabs.executions">Jobs</a>
6262
</li>
63-
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated"
63+
<li ng-hide="user.authenticationEnabled && !user.isAuthenticated" roles="['ROLE_VIEW']"
6464
ng-show="features.analyticsEnabled" ng-class="{ active: $state.includes('home.analytics') }">
6565
<a ui-sref="home.analytics.tabs.dashboard">Analytics</a>
6666
</li>
@@ -81,6 +81,5 @@
8181
<div growl></div>
8282
<div ui-view ng-cloak cg-busy="{promise:cgbusy,delay:0,minDuration:500}"></div>
8383
<script src="lib/requirejs/require.js" data-main="scripts/main"></script>
84-
8584
</body>
8685
</html>

ui/app/scripts/app/views/apps-list.html

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
<div>
55
<table class="col-lg-12 tab-content-header"><tr>
66
<td class="col-xs-8">
7-
<button id="registerAppsButton" type="button" ng-click="registerApps()"
7+
<button id="registerAppsButton" roles="['ROLE_CREATE']" type="button" ng-click="registerApps()"
88
class="btn btn-default"
99
><span class="glyphicon glyphicon-plus"></span>
1010
Register Application(s)
1111
</button>
12-
<button id="unregisterSelectedAppsButton" type="button" ng-click="unregisterSelectedApps()"
12+
<button id="unregisterSelectedAppsButton" roles="['ROLE_CREATE']" type="button" ng-click="unregisterSelectedApps()"
1313
class="btn btn-default" ng-disabled="isNoneSelected()"
1414
><span class="glyphicon glyphicon-trash"></span>
1515
Unregister Application(s)
1616
</button>
17-
<button id="bulkImportAppsButton" type="button" ng-click="bulkImportApps()"
17+
<button id="bulkImportAppsButton" roles="['ROLE_CREATE']" type="button" ng-click="bulkImportApps()"
1818
class="btn btn-default"
1919
><span class="glyphicon glyphicon-import"></span>
2020
Bulk Import Applications
@@ -29,7 +29,8 @@
2929
<thead>
3030
<tr>
3131
<th>
32-
<input id="selectAllAppsCheckbox" type="checkbox" ng-model="toggleSelectAll" ng-model-options="{ getterSetter: true }" ui-indeterminate="isSomeButNotAllSelected()"/>
32+
<input id="selectAllAppsCheckbox" type="checkbox" ng-model="toggleSelectAll" ng-model-options="{ getterSetter: true }" ui-indeterminate="isSomeButNotAllSelected()"
33+
roles="['ROLE_CREATE']"/>
3334
</th>
3435
<th>Name</th>
3536
<th>Type</th>
@@ -40,7 +41,7 @@
4041
<tbody>
4142

4243
<tr dir-paginate="item in pageable.items | itemsPerPage: pageable.pageSize" total-items="pageable.total">
43-
<td><input type="checkbox" ng-model="item.select" ng-model-options="{ getterSetter: true }"/></td>
44+
<td><input type="checkbox" ng-model="item.select" ng-model-options="{ getterSetter: true }" roles="['ROLE_CREATE']"/></td>
4445
<td>{{item.name}}</td>
4546
<td>{{item.type}}</td>
4647
<td>{{item.uri}}</td>
@@ -51,7 +52,7 @@
5152
</button>
5253
</td>
5354
<td class="action-column">
54-
<button type="button" ng-click="unregister(item, $index)"
55+
<button roles="['ROLE_CREATE']" type="button" ng-click="unregister(item, $index)"
5556
class="btn btn-default" title="Unregister"
5657
><span class="glyphicon glyphicon-trash"></span>
5758
</button>

ui/app/scripts/auth/controllers/login.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* @author Gunnar Hillert
2121
* @author Alex Boyko
2222
*/
23+
2324
define([], function () {
2425
'use strict';
2526
return ['$scope', '$state', 'userService', 'DataflowUtils', '$log', '$rootScope', '$http',
@@ -36,9 +37,21 @@ define([], function () {
3637
$rootScope.user.isFormLogin = true;
3738
$http.defaults.headers.common[$rootScope.xAuthTokenHeaderName] = response.data;
3839

40+
var securityInfoUrl = '/security/info';
41+
var timeout = 20000;
42+
var promiseHttp = $http.get(securityInfoUrl, {timeout: timeout});
3943
utils.growl.success('User ' + $scope.loginForm.username + ' logged in.');
4044
$scope.loginForm = {};
41-
$state.go('home.apps.tabs.appsList');
45+
46+
promiseHttp.then(function(response) {
47+
console.log('Security info retrieved ...', response.data);
48+
$rootScope.user.roles = response.data.roles;
49+
$state.go('home.apps.tabs.appsList');
50+
}, function(errorResponse) {
51+
var errorMessage = 'Error retrieving security info from ' + securityInfoUrl + ' (timeout: ' + timeout + 'ms)';
52+
console.log(errorMessage, errorResponse);
53+
$('.splash .container').html(errorMessage);
54+
});
4255
},
4356
function(response) {
4457
utils.growl.error(response.data[0].message);

ui/app/scripts/auth/services.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ define(['angular'], function (angular) {
2929
authenticationEnabled: securityInfo.authenticationEnabled,
3030
isAuthenticated: securityInfo.authenticated,
3131
username: securityInfo.username,
32+
roles: securityInfo.roles,
33+
hasRole: function(role) {
34+
if (user.roles.indexOf(role) >= 0){
35+
return true;
36+
}
37+
else {
38+
return false;
39+
}
40+
},
3241
isFormLogin: false
3342
};
3443
return user;

ui/app/scripts/directives.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2016 the original author or authors.
2+
* Copyright 2014-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,43 @@
2323
define(['angular', 'xregexp', 'moment'], function(angular) {
2424
'use strict';
2525
angular.module('dataflowMain.directives', [])
26+
.directive('roles', ['userService', '$rootScope', function(userService, $rootScope) {
27+
28+
function applyRoles(scope, elem) {
29+
var found = false;
30+
31+
if(userService.isAuthenticated){
32+
angular.forEach(scope.roles, function(role){
33+
found = userService.hasRole(role);
34+
console.log('Needed one for the following roles ' + scope.roles + '. Found: ' + found);
35+
});
36+
}
37+
else {
38+
found = true;
39+
}
40+
if (found) {
41+
elem.show();
42+
}
43+
else {
44+
elem.hide();
45+
}
46+
}
47+
48+
return {
49+
restrict: 'A',
50+
scope: {
51+
roles: '='
52+
},
53+
link: function (scope, elem) {
54+
scope.$watch('userService.isAuthenticated', function() {
55+
applyRoles(scope, elem);
56+
}, true);
57+
$rootScope.$watch('user.roles', function() {
58+
applyRoles(scope, elem);
59+
}, true);
60+
}
61+
};
62+
}])
2663
.directive('dataflowParseUrls', [function() {
2764
var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi;
2865

ui/app/scripts/routes.js

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ define(['./app'], function (dashboard) {
5757
template: '<ui-view/>',
5858
data:{
5959
authenticate: true,
60+
roles: ['ROLE_VIEW'],
6061
feature: 'tasksEnabled'
6162
}
6263
})
@@ -65,6 +66,7 @@ define(['./app'], function (dashboard) {
6566
template: '<ui-view/>',
6667
data:{
6768
authenticate: true,
69+
roles: ['ROLE_VIEW'],
6870
feature: 'tasksEnabled'
6971
}
7072
})
@@ -73,29 +75,33 @@ define(['./app'], function (dashboard) {
7375
template: '<ui-view/>',
7476
data: {
7577
authenticate: true,
78+
roles: ['ROLE_VIEW'],
7679
feature: 'analyticsEnabled'
7780
}
7881
})
7982
.state('home.apps', {
8083
abstract: true,
8184
template: '<ui-view/>',
8285
data: {
83-
authenticate: true
86+
authenticate: true,
87+
roles: ['ROLE_VIEW']
8488
}
8589
})
8690
.state('home.streams', {
8791
abstract:true,
8892
template: '<ui-view/>',
8993
data:{
9094
authenticate: true,
95+
roles: ['ROLE_VIEW'],
9196
feature: 'streamsEnabled'
9297
}
9398
})
9499
.state('home.runtime', {
95100
abstract:true,
96101
template: '<ui-view/>',
97102
data:{
98-
authenticate: true
103+
authenticate: true,
104+
roles: ['ROLE_VIEW']
99105
}
100106
})
101107
.state('home.jobs.tabs', {
@@ -147,6 +153,13 @@ define(['./app'], function (dashboard) {
147153
authenticate: false
148154
}
149155
})
156+
.state('home.rolesMissing', {
157+
url : '/roles-missing',
158+
templateUrl : sharedTemplatesPath + '/roles-missing.html',
159+
data:{
160+
authenticate: false
161+
}
162+
})
150163
.state('home.streams.tabs', {
151164
url : 'streams',
152165
abstract:true,
@@ -444,6 +457,19 @@ define(['./app'], function (dashboard) {
444457
$state.go('login');
445458
event.preventDefault();
446459
}
460+
else if (userService.authenticationEnabled && toState.data.authenticate &&
461+
userService.isAuthenticated && toState.data.roles && toState.data.roles.length > 0) {
462+
$log.info('State requires one of the following roles: ' + toState.data.roles);
463+
var found = false;
464+
angular.forEach(toState.data.roles, function(role){
465+
found = userService.hasRole(role);
466+
});
467+
if (!found) {
468+
$log.info('You do not have any of the necessary role(s) ' + toState.data.roles);
469+
$state.go('home.rolesMissing', {feature: toState.data.roles});
470+
event.preventDefault();
471+
}
472+
}
447473
});
448474
});
449475
return dashboard;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<h1>Roles Missing</h1>
2+
3+
<p class="index-page--subtitle">
4+
It appears that you are missing the proper roles to use the Dashboard. Please contact your administrator to rectify the
5+
situation.
6+
</p>

ui/app/scripts/stream/views/definitions.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,21 @@
5050
</button>
5151
</td>
5252
<td class="action-column">
53-
<button type="button" ng-click="undeployStream(item)"
53+
<button type="button" ng-click="undeployStream(item)" roles="['ROLE_CREATE']"
5454
ng-disabled="item.status === 'deploying' || item.status === 'undeployed'"
5555
class="btn btn-default"
5656
><span class="glyphicon glyphicon-stop"></span> Undeploy
5757
</button>
5858
</td>
5959
<td class="action-column">
60-
<button type="button" ng-click="deployStream(item)"
60+
<button type="button" ng-click="deployStream(item)" roles="['ROLE_CREATE']"
6161
ng-disabled="item.status === 'deploying' || item.status === 'deployed' || item.status === 'incomplete' || item.status === 'failed'"
6262
class="btn btn-default"
6363
><span class="glyphicon glyphicon-play"></span> Deploy
6464
</button>
6565
</td>
6666
<td class="action-column">
67-
<button type="button" ng-click="clickModal(item)"
67+
<button type="button" ng-click="clickModal(item)" roles="['ROLE_CREATE']"
6868
class="btn btn-default" data-toggle="modal" data-target="#confirm-destroy"
6969
><span class="glyphicon glyphicon-remove"></span> Destroy
7070
</button>

ui/app/scripts/stream/views/streams.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ <h1 class="no-user-selection">Streams</h1>
1010
<li ng-class="{ active: $state.includes('home.streams.tabs.definitions') }"><a
1111
ui-sref="home.streams.tabs.definitions">Definitions</a>
1212
</li>
13-
<li ng-class="{ active: $state.includes('home.streams.tabs.create') }"><a
13+
<li ng-class="{ active: $state.includes('home.streams.tabs.create') }" roles="['ROLE_CREATE']"><a
1414
ui-sref="home.streams.tabs.create">Create Stream</a>
1515
</ul>
1616
<div class="tab-content">

ui/app/scripts/task/views/definitions.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<table class="col-lg-12 tab-content-header"><tr>
66
<td class="col-xs-8">
77
<button id="bulkDefineTasksButton" type="button" ng-click="bulkDefineTasks()"
8-
class="btn btn-default"
8+
class="btn btn-default" roles="['ROLE_CREATE']"
99
><span class="glyphicon glyphicon-import"></span>
1010
Bulk Define Tasks
1111
</button>

0 commit comments

Comments
 (0)