summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/private/Authentication/Token/DefaultToken.php15
-rw-r--r--lib/private/Authentication/Token/DefaultTokenMapper.php24
-rw-r--r--lib/private/Authentication/Token/DefaultTokenProvider.php17
-rw-r--r--lib/private/Authentication/Token/IProvider.php11
-rw-r--r--lib/private/Authentication/Token/IToken.php11
-rw-r--r--lib/private/Lockdown/LockdownManager.php2
-rw-r--r--settings/Controller/AuthSettingsController.php16
-rw-r--r--settings/css/settings.css27
-rw-r--r--settings/js/authtoken_view.js35
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();