Signed-off-by: Robin Appelman <icewind@owncloud.com>tags/v11.0RC2
@@ -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) { |
@@ -87,6 +87,30 @@ class DefaultTokenMapper extends Mapper { | |||
return DefaultToken::fromRow($data); | |||
} | |||
/** | |||
* 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 | |||
* |
@@ -145,7 +145,7 @@ class DefaultTokenProvider implements IProvider { | |||
} | |||
/** | |||
* Get a token by token id | |||
* Get a token by token | |||
* | |||
* @param string $tokenId | |||
* @throws InvalidTokenException | |||
@@ -159,6 +159,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 |
@@ -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 |
@@ -76,12 +76,17 @@ 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 | |||
* |
@@ -33,7 +33,7 @@ class LockdownManager implements ILockdownManager { | |||
} | |||
public function setToken(IToken $token) { | |||
$this->scope = $token->getScope(); | |||
$this->scope = $token->getScopeAsArray(); | |||
$this->enable(); | |||
} | |||
@@ -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 []; | |||
} | |||
} |
@@ -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, |
@@ -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(); |