diff options
-rw-r--r-- | lib/private/Authentication/Token/DefaultToken.php | 15 | ||||
-rw-r--r-- | lib/private/Authentication/Token/DefaultTokenMapper.php | 24 | ||||
-rw-r--r-- | lib/private/Authentication/Token/DefaultTokenProvider.php | 17 | ||||
-rw-r--r-- | lib/private/Authentication/Token/IProvider.php | 11 | ||||
-rw-r--r-- | lib/private/Authentication/Token/IToken.php | 11 | ||||
-rw-r--r-- | lib/private/Lockdown/LockdownManager.php | 2 | ||||
-rw-r--r-- | settings/Controller/AuthSettingsController.php | 16 | ||||
-rw-r--r-- | settings/css/settings.css | 27 | ||||
-rw-r--r-- | settings/js/authtoken_view.js | 35 |
9 files changed, 145 insertions, 13 deletions
diff --git a/lib/private/Authentication/Token/DefaultToken.php b/lib/private/Authentication/Token/DefaultToken.php index e938ff92e16..b32f9cc9866 100644 --- a/lib/private/Authentication/Token/DefaultToken.php +++ b/lib/private/Authentication/Token/DefaultToken.php @@ -124,7 +124,7 @@ class DefaultToken extends Entity implements IToken { 'name' => $this->name, 'lastActivity' => $this->lastActivity, 'type' => $this->type, - 'scope' => $this->getScope() + 'scope' => $this->getScopeAsArray() ]; } @@ -147,7 +147,18 @@ class DefaultToken extends Entity implements IToken { } public function getScope() { - return json_decode(parent::getScope(), true); + return parent::getScope(); + } + + public function getScopeAsArray() { + $scope = json_decode($this->getScope(), true); + if (!$scope) { + return [ + 'filesystem'=> true, + 'apps' => [] + ]; + } + return $scope; } public function setScope($scope) { diff --git a/lib/private/Authentication/Token/DefaultTokenMapper.php b/lib/private/Authentication/Token/DefaultTokenMapper.php index bfcb54c66c0..32551a9b37c 100644 --- a/lib/private/Authentication/Token/DefaultTokenMapper.php +++ b/lib/private/Authentication/Token/DefaultTokenMapper.php @@ -88,6 +88,30 @@ class DefaultTokenMapper extends Mapper { } /** + * Get the user UID for the given token + * + * @param string $token + * @throws DoesNotExistException + * @return DefaultToken + */ + public function getTokenById($token) { + /* @var $qb IQueryBuilder */ + $qb = $this->db->getQueryBuilder(); + $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'type', 'token', 'last_activity', 'last_check', 'scope') + ->from('authtoken') + ->where($qb->expr()->eq('id', $qb->createParameter('id'))) + ->setParameter('id', $token) + ->execute(); + + $data = $result->fetch(); + $result->closeCursor(); + if ($data === false) { + throw new DoesNotExistException('token does not exist'); + }; + return DefaultToken::fromRow($data); + } + + /** * Get all token of a user * * The provider may limit the number of result rows in case of an abuse diff --git a/lib/private/Authentication/Token/DefaultTokenProvider.php b/lib/private/Authentication/Token/DefaultTokenProvider.php index 87f434c684c..0fdbc4a51dd 100644 --- a/lib/private/Authentication/Token/DefaultTokenProvider.php +++ b/lib/private/Authentication/Token/DefaultTokenProvider.php @@ -145,7 +145,7 @@ class DefaultTokenProvider implements IProvider { } /** - * Get a token by token id + * Get a token by token * * @param string $tokenId * @throws InvalidTokenException @@ -160,6 +160,21 @@ class DefaultTokenProvider implements IProvider { } /** + * Get a token by token id + * + * @param string $tokenId + * @throws InvalidTokenException + * @return DefaultToken + */ + public function getTokenById($tokenId) { + try { + return $this->mapper->getTokenById($tokenId); + } catch (DoesNotExistException $ex) { + throw new InvalidTokenException(); + } + } + + /** * @param string $oldSessionId * @param string $sessionId * @throws InvalidTokenException diff --git a/lib/private/Authentication/Token/IProvider.php b/lib/private/Authentication/Token/IProvider.php index ce14a5880c5..9f280263d76 100644 --- a/lib/private/Authentication/Token/IProvider.php +++ b/lib/private/Authentication/Token/IProvider.php @@ -50,7 +50,16 @@ interface IProvider { * @throws InvalidTokenException * @return IToken */ - public function getToken($tokenId) ; + public function getToken($tokenId); + + /** + * Get a token by token id + * + * @param string $tokenId + * @throws InvalidTokenException + * @return DefaultToken + */ + public function getTokenById($tokenId); /** * Duplicate an existing session token diff --git a/lib/private/Authentication/Token/IToken.php b/lib/private/Authentication/Token/IToken.php index a6ba392907d..71f52fd6c03 100644 --- a/lib/private/Authentication/Token/IToken.php +++ b/lib/private/Authentication/Token/IToken.php @@ -76,13 +76,18 @@ interface IToken extends JsonSerializable { /** * Get the authentication scope for this token * - * If the scope is null no limitations exist for the token - * - * @return array|null + * @return string */ public function getScope(); /** + * Get the authentication scope for this token + * + * @return array + */ + public function getScopeAsArray(); + + /** * Set the authentication scope for this token * * @param array|null $scope diff --git a/lib/private/Lockdown/LockdownManager.php b/lib/private/Lockdown/LockdownManager.php index 150b54bdba2..c34f7e01b65 100644 --- a/lib/private/Lockdown/LockdownManager.php +++ b/lib/private/Lockdown/LockdownManager.php @@ -33,7 +33,7 @@ class LockdownManager implements ILockdownManager { } public function setToken(IToken $token) { - $this->scope = $token->getScope(); + $this->scope = $token->getScopeAsArray(); $this->enable(); } diff --git a/settings/Controller/AuthSettingsController.php b/settings/Controller/AuthSettingsController.php index 58994f0d59c..f097abf910b 100644 --- a/settings/Controller/AuthSettingsController.php +++ b/settings/Controller/AuthSettingsController.php @@ -180,4 +180,20 @@ class AuthSettingsController extends Controller { return []; } + /** + * @NoAdminRequired + * @NoSubadminRequired + * + * @param int $id + * @param array $scope + */ + public function update($id, array $scope) { + $token = $this->tokenProvider->getTokenById($id); + $token->setScope([ + 'filesystem' => $scope['filesystem'], + 'app' => array_values($scope['apps']) + ]); + $this->tokenProvider->updateToken($token); + return []; + } } diff --git a/settings/css/settings.css b/settings/css/settings.css index debf69dbae2..7eff9df1d97 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -162,16 +162,35 @@ table.nostyle td { padding: 0.2em 0; } max-width: 200px; white-space: nowrap; overflow: hidden; + vertical-align: top; + position: relative; } -#sessions tr *:nth-child(2), -#apppasswords tr *:nth-child(2) { +#sessions tr>*:nth-child(2), +#apppasswords tr>*:nth-child(2) { text-align: right; } -#sessions .token-list td a.icon, -#apppasswords .token-list td a.icon { +#sessions .token-list a.icon, +#apppasswords .token-list a.icon { display: block; opacity: 0.6; + margin-top: 4px; +} + +#sessions .token-list td div.configure, +#apppasswords .token-list td div.configure { + display: none; +} + +#sessions .token-list tr.active div.configure, +#apppasswords .token-list tr.active div.configure { + display: block; + padding-left: 10px; +} + +#sessions .token-list tr.active .token-name, +#apppasswords .token-list tr.active .token-name { + display: none; } #new-app-login-name, diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index 361b5dcc7a8..54561ffd1e3 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -27,7 +27,13 @@ var TEMPLATE_TOKEN = '<tr data-id="{{id}}">' - + '<td class="has-tooltip" title="{{title}}"><span class="token-name">{{name}}</span></td>' + + '<td class="has-tooltip" title="{{title}}">' + + '<span class="token-name">{{name}}</span>' + + '<div class="configure">' + + '<input class="filesystem checkbox" type="checkbox" id="{{id}}_filesystem" {{#if scope.filesystem}}checked{{/if}}/>' + + '<label for="{{id}}_filesystem">' + t('core', 'Allow filesystem access') + '</label><br/>' + + '</div>' + + '</td>' + '<td><span class="last-activity has-tooltip" title="{{lastActivityTime}}">{{lastActivity}}</span></td>' + '<td class="icon">' + '{{#if canScope}}' @@ -211,6 +217,8 @@ var $el = $(el); $el.on('click', 'a.icon-delete', _.bind(_this._onDeleteToken, _this)); + $el.on('click', 'a.icon-settings', _.bind(_this._onConfigureToken, _this)); + $el.on('change', 'input.filesystem', _.bind(_this._onSetTokenScope, _this)); }); this._form = $('#app-password-form'); @@ -332,6 +340,13 @@ this._addAppPasswordBtn.toggleClass('icon-loading-small', state); }, + _onConfigureToken: function (event) { + var $target = $(event.target); + var $row = $target.closest('tr'); + $row.toggleClass('active'); + var id = $row.data('id'); + }, + _onDeleteToken: function (event) { var $target = $(event.target); var $row = $target.closest('tr'); @@ -360,6 +375,24 @@ }); }, + _onSetTokenScope: function (event) { + var $target = $(event.target); + var $row = $target.closest('tr'); + var id = $row.data('id'); + + var token = this.collection.get(id); + if (_.isUndefined(token)) { + // Ignore event + return; + } + + var scope = token.get('scope'); + scope.filesystem = $target.is(":checked"); + + token.set('scope', scope); + token.save(); + }, + _toggleFormResult: function (showForm) { if (showForm) { this._result.slideUp(); |