diff options
author | Roeland Jago Douma <rullzer@users.noreply.github.com> | 2016-11-16 16:17:28 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-16 16:17:28 +0100 |
commit | 61453f5fd5eb3e742d1c757def36ce8f6be408f3 (patch) | |
tree | 6dfbb42c7d7f062234e54de6a19f333c97e5aece /settings | |
parent | 5f789fdebcd67ff7374becd9fd9cb28727a191de (diff) | |
parent | e633f2f8dff0ae99e7621b5c459474887c965c0e (diff) | |
download | nextcloud-server-61453f5fd5eb3e742d1c757def36ce8f6be408f3.tar.gz nextcloud-server-61453f5fd5eb3e742d1c757def36ce8f6be408f3.zip |
Merge pull request #719 from nextcloud/lockdown
Allow restricting of app password permissions
Diffstat (limited to 'settings')
-rw-r--r-- | settings/Controller/AuthSettingsController.php | 20 | ||||
-rw-r--r-- | settings/css/settings.css | 57 | ||||
-rw-r--r-- | settings/js/authtoken_view.js | 53 |
3 files changed, 118 insertions, 12 deletions
diff --git a/settings/Controller/AuthSettingsController.php b/settings/Controller/AuthSettingsController.php index 58994f0d59c..4e3d05a14e8 100644 --- a/settings/Controller/AuthSettingsController.php +++ b/settings/Controller/AuthSettingsController.php @@ -135,11 +135,13 @@ class AuthSettingsController extends Controller { $token = $this->generateRandomDeviceToken(); $deviceToken = $this->tokenProvider->generateToken($token, $this->uid, $loginName, $password, $name, IToken::PERMANENT_TOKEN); + $tokenData = $deviceToken->jsonSerialize(); + $tokenData['canDelete'] = true; return [ 'token' => $token, 'loginName' => $loginName, - 'deviceToken' => $deviceToken + 'deviceToken' => $tokenData ]; } @@ -180,4 +182,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 37197b9550c..9008ba5a985 100644 --- a/settings/css/settings.css +++ b/settings/css/settings.css @@ -149,6 +149,13 @@ table.nostyle td { padding: 0.2em 0; } padding: 10px 10px 10px 0; } +#sessions .token-list td.more, +#apppasswords .token-list td.more { + overflow: visible; + position: relative; + width: 16px; +} + #sessions .token-list td, #apppasswords .token-list td { border-top: 1px solid #DDD; @@ -156,18 +163,60 @@ 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-delete, -#apppasswords .token-list td a.icon-delete { +#sessions .token-list td > a.icon, +#apppasswords .token-list td > a.icon { + opacity: 0; + transition: opacity 0.5s; +} + +#sessions .token-list a.icon, +#apppasswords .token-list a.icon { + margin-top: 4px; display: block; +} + +#sessions .token-list tr:hover td > a.icon, +#apppasswords .token-list tr:hover td > a.icon, +#sessions .token-list tr.active td > a.icon, +#apppasswords .token-list tr.active td > a.icon{ opacity: 0.6; } +#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; + position: absolute; + top: 45px; + right: -5px; + padding: 10px; +} + +#sessions .token-list tr.active div.configure > *, +#apppasswords .token-list tr.active div.configure > *{ + margin-top: 5px; + margin-bottom: 5px; + display: inline-block; +} + +#sessions .token-list tr.active a.icon-delete, +#apppasswords .token-list tr.active a.icon-delete { + background-position: left; + padding-left: 20px; +} + #new-app-login-name, #new-app-password { width: 186px; diff --git a/settings/js/authtoken_view.js b/settings/js/authtoken_view.js index 6eb04b63f20..20fe5235eb0 100644 --- a/settings/js/authtoken_view.js +++ b/settings/js/authtoken_view.js @@ -27,13 +27,22 @@ 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>' + + '</td>' + '<td><span class="last-activity has-tooltip" title="{{lastActivityTime}}">{{lastActivity}}</span></td>' + + '<td class="more">' + + '{{#if showMore}}<a class="icon icon-more"/>{{/if}}' + + '<div class="popovermenu bubble open menu configure">' + + '{{#if canScope}}' + + '<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/>' + + '{{/if}}' + '{{#if canDelete}}' - + '<td><a class="icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '"></a></td>' - + '{{else}}' - + '<td></td>' + + '<a class="icon icon-delete has-tooltip" title="' + t('core', 'Disconnect') + '">' + t('core', 'Revoke') +'</a>' + '{{/if}}' + + '</div>' + + '</td>' + '<tr>'; var SubView = OC.Backbone.View.extend({ @@ -70,7 +79,7 @@ var list = this.$('.token-list'); var tokens = this.collection.filter(function (token) { - return parseInt(token.get('type'), 10) === _this.type; + return token.get('type') === _this.type; }); list.html(''); @@ -78,7 +87,7 @@ this._toggleHeader(tokens.length > 0); tokens.forEach(function (token) { - var viewData = this._formatViewData(token.toJSON()); + var viewData = this._formatViewData(token); var html = _this.template(viewData); var $html = $(html); $html.find('.has-tooltip').tooltip({container: 'body'}); @@ -94,10 +103,13 @@ this.$('.hidden-when-empty').toggleClass('hidden', !show); }, - _formatViewData: function (viewData) { + _formatViewData: function (token) { + var viewData = token.toJSON(); var ts = viewData.lastActivity * 1000; viewData.lastActivity = OC.Util.relativeModifiedDate(ts); viewData.lastActivityTime = OC.Util.formatDate(ts, 'LLL'); + viewData.canScope = token.get('type') === 1; + viewData.showMore = viewData.canScope || viewData.canDelete; // preserve title for cases where we format it further viewData.title = viewData.name; @@ -204,6 +216,8 @@ var $el = $(el); $el.on('click', 'a.icon-delete', _.bind(_this._onDeleteToken, _this)); + $el.on('click', '.icon-more', _.bind(_this._onConfigureToken, _this)); + $el.on('change', 'input.filesystem', _.bind(_this._onSetTokenScope, _this)); }); this._form = $('#app-password-form'); @@ -325,6 +339,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'); @@ -353,6 +374,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(); |