diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/Authentication/Token/PublicKeyTokenMapper.php | 26 | ||||
-rw-r--r-- | lib/private/Authentication/Token/PublicKeyTokenProvider.php | 6 | ||||
-rw-r--r-- | lib/private/User/Session.php | 1 | ||||
-rw-r--r-- | lib/public/AppFramework/Db/QBMapper.php | 42 |
4 files changed, 48 insertions, 27 deletions
diff --git a/lib/private/Authentication/Token/PublicKeyTokenMapper.php b/lib/private/Authentication/Token/PublicKeyTokenMapper.php index 0db5c4f53e7..5b97e557219 100644 --- a/lib/private/Authentication/Token/PublicKeyTokenMapper.php +++ b/lib/private/Authentication/Token/PublicKeyTokenMapper.php @@ -182,7 +182,7 @@ class PublicKeyTokenMapper extends QBMapper { } /** - * Update the last activity timestamp + * Update the last activity timestamp and save all saved fields * * In highly concurrent setups it can happen that two parallel processes * trigger the update at (nearly) the same time. In that special case it's @@ -192,7 +192,7 @@ class PublicKeyTokenMapper extends QBMapper { * * Example: * - process 1 (P1) reads the token at timestamp 1500 - * - process 1 (P2) reads the token at timestamp 1501 + * - process 2 (P2) reads the token at timestamp 1501 * - activity update interval is 100 * * This means @@ -206,17 +206,21 @@ class PublicKeyTokenMapper extends QBMapper { * but the comparison on last_activity will still not be truthy and the * token row is not updated a second time * - * @param IToken $token + * @param PublicKeyToken $token * @param int $now */ - public function updateActivity(IToken $token, int $now): void { - $qb = $this->db->getQueryBuilder(); - $update = $qb->update($this->getTableName()) - ->set('last_activity', $qb->createNamedParameter($now, IQueryBuilder::PARAM_INT)) - ->where( - $qb->expr()->eq('id', $qb->createNamedParameter($token->getId(), IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT), - $qb->expr()->lt('last_activity', $qb->createNamedParameter($now - 15, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT) - ); + public function updateActivity(PublicKeyToken $token, int $now): void { + $token->setLastActivity($now); + $update = $this->createUpdateQuery($token); + + $updatedFields = $token->getUpdatedFields(); + unset($updatedFields['lastActivity']); + + // if no other fields are updated, we add the extra filter to prevent duplicate updates + if (count($updatedFields) === 0) { + $update->andWhere($update->expr()->lt('last_activity', $update->createNamedParameter($now - 15, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)); + } + $update->executeStatement(); } diff --git a/lib/private/Authentication/Token/PublicKeyTokenProvider.php b/lib/private/Authentication/Token/PublicKeyTokenProvider.php index 767ece1e551..809c39474e2 100644 --- a/lib/private/Authentication/Token/PublicKeyTokenProvider.php +++ b/lib/private/Authentication/Token/PublicKeyTokenProvider.php @@ -299,10 +299,12 @@ class PublicKeyTokenProvider implements IProvider { $activityInterval = $this->config->getSystemValueInt('token_auth_activity_update', 60); $activityInterval = min(max($activityInterval, 0), 300); + $updatedFields = $token->getUpdatedFields(); + unset($updatedFields['lastActivity']); + /** @var PublicKeyToken $token */ $now = $this->time->getTime(); - if ($token->getLastActivity() < ($now - $activityInterval)) { - $token->setLastActivity($now); + if ($token->getLastActivity() < ($now - $activityInterval) || count($updatedFields)) { $this->mapper->updateActivity($token, $now); $this->cacheToken($token); } diff --git a/lib/private/User/Session.php b/lib/private/User/Session.php index e5d27172519..8226e3c95f5 100644 --- a/lib/private/User/Session.php +++ b/lib/private/User/Session.php @@ -757,7 +757,6 @@ class Session implements IUserSession, Emitter { if ($dbToken instanceof PublicKeyToken) { $dbToken->setLastActivity($now); } - $this->tokenProvider->updateToken($dbToken); return true; } diff --git a/lib/public/AppFramework/Db/QBMapper.php b/lib/public/AppFramework/Db/QBMapper.php index badd2483b58..ad9f772095a 100644 --- a/lib/public/AppFramework/Db/QBMapper.php +++ b/lib/public/AppFramework/Db/QBMapper.php @@ -146,22 +146,15 @@ abstract class QBMapper { } /** - * Updates an entry in the db from an entity + * Create an update query that saves all updated fields * - * @param Entity $entity the entity that should be created - * @psalm-param T $entity the entity that should be created - * @return Entity the saved entity with the set id - * @psalm-return T the saved entity with the set id - * @throws Exception - * @throws \InvalidArgumentException if entity has no id - * @since 14.0.0 + * @param Entity $entity the entity that should be updated + * @psalm-param T $entity the entity that should be updated + * @return IQueryBuilder + * @since 25.0.0 */ - public function update(Entity $entity): Entity { - // if entity wasn't changed it makes no sense to run a db query + protected function createUpdateQuery(Entity $entity): IQueryBuilder { $properties = $entity->getUpdatedFields(); - if (\count($properties) === 0) { - return $entity; - } // entity needs an id $id = $entity->getId(); @@ -193,6 +186,29 @@ abstract class QBMapper { $qb->where( $qb->expr()->eq('id', $qb->createNamedParameter($id, $idType)) ); + + return $qb; + } + + /** + * Updates an entry in the db from an entity + * + * @param Entity $entity the entity that should be created + * @psalm-param T $entity the entity that should be created + * @return Entity the saved entity with the set id + * @psalm-return T the saved entity with the set id + * @throws Exception + * @throws \InvalidArgumentException if entity has no id + * @since 14.0.0 + */ + public function update(Entity $entity): Entity { + // if entity wasn't changed it makes no sense to run a db query + $properties = $entity->getUpdatedFields(); + if (\count($properties) === 0) { + return $entity; + } + + $qb = $this->createUpdateQuery($entity); $qb->executeStatement(); return $entity; |