Merge "Users may now issue their own access tokens."
This commit is contained in:
commit
c4e7615817
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