Users may now issue their own access tokens.
A user may now issue their own access tokens, as well as deactivate existing access tokens, using the web UI. It may be used for direct API access using the python SDK. Change-Id: I01a59c4fad6459299ee846879065b256326efedb
This commit is contained in:
parent
40d06c9cf0
commit
4b02ea285f
63
src/app/profile/controller/profile_token_new_controller.js
Normal file
63
src/app/profile/controller/profile_token_new_controller.js
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Issue token controller.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProfileTokenNewController',
|
||||
function ($q, $log, $scope, $modalInstance, UserToken, user) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Flag for the UI to indicate that we're saving.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
$scope.isSaving = false;
|
||||
|
||||
/**
|
||||
* The new token.
|
||||
*
|
||||
* @type {UserToken}
|
||||
*/
|
||||
$scope.token = new UserToken({
|
||||
user_id: user.id,
|
||||
expires_in: 3600
|
||||
});
|
||||
|
||||
/**
|
||||
* Saves the project group
|
||||
*/
|
||||
$scope.save = function () {
|
||||
$scope.isSaving = true;
|
||||
$scope.token.$create(
|
||||
function (token) {
|
||||
$modalInstance.close(token);
|
||||
$scope.isSaving = false;
|
||||
},
|
||||
function () {
|
||||
$scope.isSaving = false;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Close this modal without saving.
|
||||
*/
|
||||
$scope.close = function () {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
});
|
70
src/app/profile/controller/profile_tokens_controller.js
Normal file
70
src/app/profile/controller/profile_tokens_controller.js
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* User profile controller for all of a user's auth tokens.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProfileTokensController',
|
||||
function ($scope, UserToken, tokens, $modal) {
|
||||
'use strict';
|
||||
|
||||
$scope.tokens = tokens;
|
||||
|
||||
$scope.deleteToken = function (token) {
|
||||
token.$delete(function () {
|
||||
var idx = $scope.tokens.indexOf(token);
|
||||
if (idx > -1) {
|
||||
$scope.tokens.splice(idx, 1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.issueToken = function () {
|
||||
$modal.open({
|
||||
templateUrl: 'app/profile/template/token_new.html',
|
||||
controller: 'ProfileTokenNewController',
|
||||
resolve: {
|
||||
user: function (CurrentUser) {
|
||||
return CurrentUser.resolve();
|
||||
}
|
||||
}
|
||||
}).result.then(function (token) {
|
||||
// On success, append the token.
|
||||
$scope.tokens.push(token);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Controller for a single token row within the profile token view.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProfileTokenItemController',
|
||||
function ($scope, AccessToken) {
|
||||
'use strict';
|
||||
|
||||
var now = new Date();
|
||||
|
||||
// Render the expiration date.
|
||||
$scope.created = new Date($scope.token.created_at);
|
||||
$scope.expires = new Date($scope.token.created_at);
|
||||
$scope.expires.setSeconds($scope.expires.getSeconds() +
|
||||
$scope.token.expires_in);
|
||||
|
||||
$scope.expired = $scope.expires.getTime() < now.getTime();
|
||||
$scope.current =
|
||||
$scope.token.access_token === AccessToken.getAccessToken();
|
||||
});
|
@ -23,8 +23,8 @@
|
||||
* @author Michael Krotscheck
|
||||
*/
|
||||
angular.module('sb.profile',
|
||||
['sb.services', 'sb.templates', 'sb.auth', 'ui.router', 'ui.bootstrap']
|
||||
)
|
||||
['sb.services', 'sb.templates', 'sb.auth', 'ui.router', 'ui.bootstrap']
|
||||
)
|
||||
.config(function ($stateProvider, SessionResolver, $urlRouterProvider) {
|
||||
'use strict';
|
||||
|
||||
@ -40,7 +40,7 @@ angular.module('sb.profile',
|
||||
isLoggedIn: SessionResolver.requireLoggedIn,
|
||||
currentUser: SessionResolver.requireCurrentUser
|
||||
},
|
||||
views : {
|
||||
views: {
|
||||
'submenu@': {
|
||||
templateUrl: 'app/profile/template/profile_submenu.html'
|
||||
},
|
||||
@ -53,5 +53,32 @@ angular.module('sb.profile',
|
||||
url: '/preferences',
|
||||
templateUrl: 'app/profile/template/preferences.html',
|
||||
controller: 'ProfilePreferencesController'
|
||||
})
|
||||
.state('profile.tokens', {
|
||||
url: '/tokens',
|
||||
templateUrl: 'app/profile/template/tokens.html',
|
||||
controller: 'ProfileTokensController',
|
||||
resolve: {
|
||||
tokens: function (CurrentUser, UserToken, $q) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
CurrentUser.resolve().then(
|
||||
function (currentUser) {
|
||||
UserToken.query({
|
||||
user_id: currentUser.id
|
||||
}, function (results) {
|
||||
deferred.resolve(results);
|
||||
}, function (error) {
|
||||
deferred.reject(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
function (error) {
|
||||
deferred.reject(error);
|
||||
}
|
||||
);
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
@ -17,7 +17,7 @@
|
||||
<div class="container" ng-hide="isLoading">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1>Preferences</h1>
|
||||
<h1><i class="fa fa-sb-profile-preferences"></i> Preferences</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
@ -20,4 +20,9 @@
|
||||
<i class="fa fa-sb-profile-preferences fa-lg"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li active-path="^\/profile/tokens.*">
|
||||
<a href="#!/profile/tokens" title="Authentication Tokens">
|
||||
<i class="fa fa-sb-profile-tokens fa-lg"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
102
src/app/profile/template/token_new.html
Normal file
102
src/app/profile/template/token_new.html
Normal file
@ -0,0 +1,102 @@
|
||||
<!--
|
||||
~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
~ not use this file except in compliance with the License. You may obtain
|
||||
~ a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
~ License for the specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<button type="button" class="close"
|
||||
ng-click="close()">×</button>
|
||||
<h3 class="panel-title">Issue Access Token</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<form class="form-horizontal" role="form" name="tokenForm">
|
||||
<div class="form-group">
|
||||
<label for="expires_in" class="col-sm-3 control-label">
|
||||
Expires in:
|
||||
</label>
|
||||
|
||||
<div class="col-sm-9">
|
||||
<select id="expires_in" class="form-control"
|
||||
ng-model="token.expires_in"
|
||||
required
|
||||
ng-disabled="isSaving">
|
||||
<option value="3600">1 hour</option>
|
||||
<option value="86400">1 day</option>
|
||||
<option value="604800">1 week</option>
|
||||
<option value="31536000">1 year</option>
|
||||
<option value="315360000">1 decade</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<button type="button"
|
||||
class="btn btn-primary"
|
||||
ng-click="save()"
|
||||
ng-disabled="!tokenForm.$valid || isSaving">
|
||||
Issue Token
|
||||
</button>
|
||||
<button type="button"
|
||||
ng-click="close()"
|
||||
ng-disabled="isSaving"
|
||||
class="btn btn-default">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Template for story metadata -->
|
||||
<script type="text/ng-template" id="/inline/project_row.html">
|
||||
<td class="col-xs-11">
|
||||
<div class="has-feedback has-feedback-no-label">
|
||||
<input id="project"
|
||||
type="text"
|
||||
placeholder="Select a Project"
|
||||
required
|
||||
ng-model="project"
|
||||
typeahead-editable="false"
|
||||
typeahead-wait-ms="200"
|
||||
typeahead="project as project.name for project
|
||||
in searchProjects($viewValue)"
|
||||
typeahead-loading="loadingProjects"
|
||||
typeahead-on-select="selectNewProject(index, $model)"
|
||||
typeahead-input-formatter="formatProjectName($model)"
|
||||
ng-disabled="isSaving"
|
||||
class="form-control input-sm"
|
||||
/>
|
||||
<span class="form-control-feedback text-muted
|
||||
form-control-feedback-sm">
|
||||
<i class="fa fa-refresh fa-spin" ng-show="loadingProjects"></i>
|
||||
<i class="fa fa-search" ng-hide="loadingProjects"></i>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<th class="col-xs-1"
|
||||
ng-show="projects.length > 1">
|
||||
<button type="button" class="close"
|
||||
ng-click="removeProject(index)">
|
||||
×
|
||||
</button>
|
||||
</th>
|
||||
</script>
|
78
src/app/profile/template/tokens.html
Normal file
78
src/app/profile/template/tokens.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!--
|
||||
~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
~ not use this file except in compliance with the License. You may obtain
|
||||
~ a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
~ License for the specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
|
||||
<div class="container" ng-hide="isLoading">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1><i class="fa fa-sb-profile-tokens"></i> Authentication
|
||||
Tokens</h1>
|
||||
</div>
|
||||
<div class="col-xs-9 col-sm-10">
|
||||
<p class="lead">Authorize and deauthorize authentication tokens
|
||||
for StoryBoard.</p>
|
||||
</div>
|
||||
<div class="col-xs-3 col-sm-2">
|
||||
<button type="button"
|
||||
class="btn btn-primary btn-sm pull-right"
|
||||
ng-click="issueToken()">
|
||||
<i class="fa fa-plus"></i>
|
||||
<span class="hidden-sm hidden-xs">Issue Token</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Token</th>
|
||||
<th>Issued</th>
|
||||
<th>Expires</th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="token in tokens"
|
||||
ng-controller="ProfileTokenItemController">
|
||||
<td>
|
||||
<span class="label label-success"
|
||||
ng-if="current">
|
||||
Current
|
||||
</span>
|
||||
<span class="label label-danger"
|
||||
ng-if="expired && !current">
|
||||
Expired
|
||||
</span>
|
||||
<span class="label label-info"
|
||||
ng-if="!expired && !current">
|
||||
Active
|
||||
</span>
|
||||
{{token.access_token}}
|
||||
</td>
|
||||
<td><span time-moment eventdate="created"></span></td>
|
||||
<td><span time-moment eventdate="expires"></span></td>
|
||||
<td>
|
||||
<button type="button"
|
||||
class="close"
|
||||
ng-click="deleteToken(token)"
|
||||
ng-if="!current">×</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
35
src/app/services/resource/user_token.js
Normal file
35
src/app/services/resource/user_token.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The angular resource abstraction that allows us to search, access, and
|
||||
* modify individual user's authentication tokens.
|
||||
*
|
||||
* @see ResourceFactory
|
||||
* @author Michael Krotscheck
|
||||
*/
|
||||
angular.module('sb.services').factory('UserToken',
|
||||
function (ResourceFactory) {
|
||||
'use strict';
|
||||
|
||||
var resource = ResourceFactory.build(
|
||||
'/users/:user_id/tokens/:id',
|
||||
null,
|
||||
{user_id: '@user_id', id: '@id'}
|
||||
);
|
||||
|
||||
return resource;
|
||||
});
|
@ -29,3 +29,4 @@
|
||||
.@{fa-css-prefix}-sb-admin:before { content: @fa-var-gears; }
|
||||
.@{fa-css-prefix}-sb-profile:before { content: @fa-var-user; }
|
||||
.@{fa-css-prefix}-sb-profile-preferences:before { content: @fa-var-gear; }
|
||||
.@{fa-css-prefix}-sb-profile-tokens:before { content: @fa-var-key; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user