Skip to content

Commit 3dff510

Browse files
Merge pull request #2240 from nextcloud/backport/2235/stable31
[stable31] fix(push): Check last activity and last check for age
2 parents 8763fa8 + 1f964b5 commit 3dff510

2 files changed

Lines changed: 64 additions & 2 deletions

File tree

lib/Push.php

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use OCP\AppFramework\Http;
1919
use OCP\AppFramework\Utility\ITimeFactory;
2020
use OCP\Authentication\Exceptions\InvalidTokenException;
21+
use OCP\Authentication\Token\IToken;
2122
use OCP\DB\QueryBuilder\IQueryBuilder;
2223
use OCP\Http\Client\IClientService;
2324
use OCP\ICache;
@@ -537,10 +538,23 @@ protected function validateToken(int $tokenId, int $maxAge): bool {
537538
try {
538539
// Check if the token is still valid...
539540
$token = $this->tokenProvider->getTokenById($tokenId);
540-
$this->cache->set('t' . $tokenId, $token->getLastCheck(), 600);
541+
$type = $this->callSafelyForToken($token, 'getType');
542+
if ($type === IToken::WIPE_TOKEN) {
543+
// Token does not exist any more, should drop the push device entry
544+
$this->printInfo('Device token is marked for remote wipe');
545+
$this->deletePushToken($tokenId);
546+
$this->cache->set('t' . $tokenId, 0, 600);
547+
return false;
548+
}
549+
541550
$age = $token->getLastCheck();
551+
$lastActivity = $this->callSafelyForToken($token, 'getLastActivity');
552+
if ($lastActivity) {
553+
$age = max($age, $lastActivity);
554+
}
555+
$this->cache->set('t' . $tokenId, $age, 600);
542556
} catch (InvalidTokenException) {
543-
// Token does not exist anymore, should drop the push device entry
557+
// Token does not exist any more, should drop the push device entry
544558
$this->printInfo('InvalidTokenException is thrown');
545559
$this->deletePushToken($tokenId);
546560
$this->cache->set('t' . $tokenId, 0, 600);
@@ -557,6 +571,25 @@ protected function validateToken(int $tokenId, int $maxAge): bool {
557571
return false;
558572
}
559573

574+
/**
575+
* The functions are not part of public API so we are a bit more careful
576+
* @param IToken $token
577+
* @param 'getLastActivity'|'getType' $method
578+
* @return int|null
579+
*/
580+
protected function callSafelyForToken(IToken $token, string $method): ?int {
581+
if (method_exists($token, $method) || method_exists($token, '__call')) {
582+
try {
583+
$result = $token->$method();
584+
if (is_int($result)) {
585+
return $result;
586+
}
587+
} catch (\BadFunctionCallException) {
588+
}
589+
}
590+
return null;
591+
}
592+
560593
/**
561594
* @param Key $userKey
562595
* @param array $device

tests/Unit/PushTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
use GuzzleHttp\Exception\ServerException;
1313
use OC\Authentication\Exceptions\InvalidTokenException;
1414
use OC\Authentication\Token\IProvider;
15+
use OC\Authentication\Token\PublicKeyToken;
1516
use OC\Security\IdentityProof\Key;
1617
use OC\Security\IdentityProof\Manager;
1718
use OCA\Notifications\Push;
1819
use OCP\AppFramework\Http;
1920
use OCP\AppFramework\Utility\ITimeFactory;
21+
use OCP\Authentication\Token\IToken as OCPIToken;
2022
use OCP\Http\Client\IClient;
2123
use OCP\Http\Client\IClientService;
2224
use OCP\Http\Client\IResponse;
@@ -783,4 +785,31 @@ public function testPushToDeviceTalkNotification(array $deviceTypes, bool $isTal
783785

784786
$push->pushToDevice(200718, $notification);
785787
}
788+
789+
public static function dataValidateToken(): array {
790+
return [
791+
[1239999999, 1230000000, OCPIToken::WIPE_TOKEN, false],
792+
[1230000000, 1239999999, OCPIToken::WIPE_TOKEN, false],
793+
[1230000000, 1239999999, OCPIToken::PERMANENT_TOKEN, true],
794+
[1239999999, 1230000000, OCPIToken::PERMANENT_TOKEN, true],
795+
[1230000000, 1230000000, OCPIToken::PERMANENT_TOKEN, false],
796+
];
797+
}
798+
799+
/**
800+
* @dataProvider dataValidateToken
801+
*/
802+
public function testValidateToken(int $lastCheck, int $lastActivity, int $type, bool $expected): void {
803+
$token = PublicKeyToken::fromParams([
804+
'lastCheck' => $lastCheck,
805+
'lastActivity' => $lastActivity,
806+
'type' => $type,
807+
]);
808+
809+
$this->tokenProvider->method('getTokenById')
810+
->willReturn($token);
811+
812+
$push = $this->getPush();
813+
$this->assertSame($expected, self::invokePrivate($push, 'validateToken', [42, 1234567890]));
814+
}
786815
}

0 commit comments

Comments
 (0)