aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenMapper.php26
-rw-r--r--lib/private/Authentication/Token/PublicKeyTokenProvider.php6
-rw-r--r--lib/private/User/Session.php1
-rw-r--r--lib/public/AppFramework/Db/QBMapper.php42
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;