From 4b02ea285fc2bcf4935f52e1bb7714ccb2468329 Mon Sep 17 00:00:00 2001 From: Michael Krotscheck Date: Mon, 8 Dec 2014 14:54:17 -0800 Subject: [PATCH] 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 --- .../profile_token_new_controller.js | 63 +++++++++++ .../controller/profile_tokens_controller.js | 70 ++++++++++++ src/app/profile/module.js | 33 +++++- src/app/profile/template/preferences.html | 2 +- src/app/profile/template/profile_submenu.html | 5 + src/app/profile/template/token_new.html | 102 ++++++++++++++++++ src/app/profile/template/tokens.html | 78 ++++++++++++++ src/app/services/resource/user_token.js | 35 ++++++ src/theme/base/icons.less | 1 + 9 files changed, 385 insertions(+), 4 deletions(-) create mode 100644 src/app/profile/controller/profile_token_new_controller.js create mode 100644 src/app/profile/controller/profile_tokens_controller.js create mode 100644 src/app/profile/template/token_new.html create mode 100644 src/app/profile/template/tokens.html create mode 100644 src/app/services/resource/user_token.js diff --git a/src/app/profile/controller/profile_token_new_controller.js b/src/app/profile/controller/profile_token_new_controller.js new file mode 100644 index 00000000..6dba9671 --- /dev/null +++ b/src/app/profile/controller/profile_token_new_controller.js @@ -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'); + }; + }); \ No newline at end of file diff --git a/src/app/profile/controller/profile_tokens_controller.js b/src/app/profile/controller/profile_tokens_controller.js new file mode 100644 index 00000000..51846874 --- /dev/null +++ b/src/app/profile/controller/profile_tokens_controller.js @@ -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(); + }); \ No newline at end of file diff --git a/src/app/profile/module.js b/src/app/profile/module.js index d4f74f89..1e13517e 100644 --- a/src/app/profile/module.js +++ b/src/app/profile/module.js @@ -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; + } + } }); }); \ No newline at end of file diff --git a/src/app/profile/template/preferences.html b/src/app/profile/template/preferences.html index f75342dc..d15bf939 100644 --- a/src/app/profile/template/preferences.html +++ b/src/app/profile/template/preferences.html @@ -17,7 +17,7 @@
-

Preferences

+

Preferences

diff --git a/src/app/profile/template/profile_submenu.html b/src/app/profile/template/profile_submenu.html index 3729be61..ce303322 100644 --- a/src/app/profile/template/profile_submenu.html +++ b/src/app/profile/template/profile_submenu.html @@ -20,4 +20,9 @@ +
  • + + + +
  • \ No newline at end of file diff --git a/src/app/profile/template/token_new.html b/src/app/profile/template/token_new.html new file mode 100644 index 00000000..ca329fef --- /dev/null +++ b/src/app/profile/template/token_new.html @@ -0,0 +1,102 @@ + + +
    +
    + +

    Issue Access Token

    +
    +
    +
    +
    +
    +
    + + +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    +
    + + + diff --git a/src/app/profile/template/tokens.html b/src/app/profile/template/tokens.html new file mode 100644 index 00000000..2ede3410 --- /dev/null +++ b/src/app/profile/template/tokens.html @@ -0,0 +1,78 @@ + + +
    +
    +
    +

    Authentication + Tokens

    +
    +
    +

    Authorize and deauthorize authentication tokens + for StoryBoard.

    +
    +
    + +
    +
    +
    +
    + + + + + + + + + + + + + + + + + +
    TokenIssuedExpires 
    + + Current + + + Expired + + + Active + +  {{token.access_token}} + + +
    +
    +
    +
    diff --git a/src/app/services/resource/user_token.js b/src/app/services/resource/user_token.js new file mode 100644 index 00000000..7203d3e3 --- /dev/null +++ b/src/app/services/resource/user_token.js @@ -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; + }); \ No newline at end of file diff --git a/src/theme/base/icons.less b/src/theme/base/icons.less index f8db8106..d8cbd167 100644 --- a/src/theme/base/icons.less +++ b/src/theme/base/icons.less @@ -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; }