Skip to content

Commit e14aa02

Browse files
committed
Add support for X-NC-E2EE-COUNTER
Signed-off-by: Louis Chemineau <[email protected]>
1 parent f389108 commit e14aa02

File tree

3 files changed

+47
-27
lines changed

3 files changed

+47
-27
lines changed

lib/Controller/LockingController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ public function __construct(
9494
*/
9595
public function lockFolder(int $id, ?string $shareToken = null): DataResponse {
9696
$e2eToken = $this->request->getParam('e2e-token', '');
97+
$e2eCounter = (int)$this->request->getHeader('X-NC-E2EE-COUNTER');
9798

9899
$ownerId = $this->getOwnerId($shareToken);
99100

@@ -114,7 +115,7 @@ public function lockFolder(int $id, ?string $shareToken = null): DataResponse {
114115
throw new OCSForbiddenException($this->l10n->t('You are not allowed to create the lock'));
115116
}
116117

117-
$newToken = $this->lockManager->lockFile($id, $e2eToken, $ownerId);
118+
$newToken = $this->lockManager->lockFile($id, $e2eToken, $e2eCounter, $ownerId);
118119
if ($newToken === null) {
119120
throw new OCSForbiddenException($this->l10n->t('File already locked'));
120121
}

lib/LockManager.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function __construct(
6767
/**
6868
* Lock file
6969
*/
70-
public function lockFile(int $id, string $token = '', ?string $ownerId = null): ?string {
70+
public function lockFile(int $id, string $token = '', int $e2eCounter, string $ownerId): ?string {
7171
if ($this->isLocked($id, $token, $ownerId)) {
7272
return null;
7373
}
@@ -76,6 +76,13 @@ public function lockFile(int $id, string $token = '', ?string $ownerId = null):
7676
$lock = $this->lockMapper->getByFileId($id);
7777
return $lock->getToken() === $token ? $token : null;
7878
} catch (DoesNotExistException $ex) {
79+
$metaData = $this->metaDataStorage->getMetaData($ownerId, $id);
80+
$decodedMetadata = json_decode($metaData, true);
81+
// TODO, unsure counter is the proper property name.
82+
if ($decodedMetadata['counter'] >= $e2eCounter) {
83+
throw new NotPermittedException('Received counter is not greater than the stored one');
84+
}
85+
7986
$newToken = $this->getToken();
8087
$lockEntity = new Lock();
8188
$lockEntity->setId($id);

tests/Unit/LockManagerTest.php

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ protected function setUp(): void {
9494
*
9595
* @param bool $isLocked
9696
* @param bool $lockDoesNotExist
97-
* @param string $token
97+
* @param int $token
98+
* @param bool $counter
9899
* @param bool $expectNull
99100
* @param bool $expectNewToken
100101
* @param bool $expectOldToken
101102
*/
102-
public function testLock(bool $isLocked, bool $lockDoesNotExist, string $token, bool $expectNull, bool $expectNewToken, bool $expectOldToken): void {
103+
public function testLock(bool $isLocked, bool $lockDoesNotExist, int $counter, string $token, bool $expectNull, bool $expectNewToken, bool $expectOldToken): void {
103104
$lockManager = $this->getMockBuilder(LockManager::class)
104105
->setMethods(['isLocked'])
105106
->setConstructorArgs([
@@ -114,7 +115,7 @@ public function testLock(bool $isLocked, bool $lockDoesNotExist, string $token,
114115

115116
$lockManager->expects($this->once())
116117
->method('isLocked')
117-
->with(42, $token)
118+
->with(42, $token, 'userId')
118119
->willReturn($isLocked);
119120

120121
if (!$isLocked) {
@@ -135,31 +136,41 @@ public function testLock(bool $isLocked, bool $lockDoesNotExist, string $token,
135136
}
136137

137138
if ($expectNewToken) {
138-
$this->secureRandom->expects($this->once())
139-
->method('generate')
140-
->with(64, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS)
141-
->willReturn('new-token');
142-
143-
$this->timeFactory->expects($this->once())
144-
->method('getTime')
145-
->willReturn(1337);
146-
147-
$this->lockMapper->expects($this->once())
148-
->method('insert')
149-
->with($this->callback(static function ($lock) {
150-
return ($lock instanceof Lock &&
151-
$lock->getId() === 42 &&
152-
$lock->getTimestamp() === 1337 &&
153-
$lock->getToken() === 'new-token');
154-
}));
139+
$this->metaDataStorage->expects($this->once())
140+
->method('getMetaData')
141+
->with('userId', 42)
142+
->willReturn('{"counter": 0}');
143+
144+
if ($counter > 0) {
145+
$this->secureRandom->expects($this->once())
146+
->method('generate')
147+
->with(64, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS)
148+
->willReturn('new-token');
149+
150+
$this->timeFactory->expects($this->once())
151+
->method('getTime')
152+
->willReturn(1337);
153+
154+
$this->lockMapper->expects($this->once())
155+
->method('insert')
156+
->with($this->callback(static function ($lock) {
157+
return ($lock instanceof Lock &&
158+
$lock->getId() === 42 &&
159+
$lock->getTimestamp() === 1337 &&
160+
$lock->getToken() === 'new-token');
161+
}));
162+
} else {
163+
$this->expectException(NotPermittedException::class);
164+
$this->expectExceptionMessage('Received counter is not greater than the stored one');
165+
}
155166
} else {
156167
$this->secureRandom->expects($this->never())
157168
->method('generate');
158169
$this->timeFactory->expects($this->never())
159170
->method('getTime');
160171
}
161172

162-
$actual = $lockManager->lockFile(42, $token);
173+
$actual = $lockManager->lockFile(42, $token, $counter, 'userId');
163174

164175
if ($expectNull) {
165176
$this->assertNull($actual);
@@ -174,10 +185,11 @@ public function testLock(bool $isLocked, bool $lockDoesNotExist, string $token,
174185

175186
public function lockDataProvider(): array {
176187
return [
177-
[true, false, 'correct-token123', true, false, false],
178-
[false, true, 'correct-token123', false, true, false],
179-
[false, false, 'correct-token123', false, false, true],
180-
[false, false, 'wrong-token456', true, false, false],
188+
[true, false, 1, 'correct-token123', true, false, false],
189+
[false, true, 1, 'correct-token123', false, true, false],
190+
[false, true, 0, 'correct-token123', false, true, false],
191+
[false, false, 1, 'correct-token123', false, false, true],
192+
[false, false, 1, 'wrong-token456', true, false, false],
181193
];
182194
}
183195

0 commit comments

Comments
 (0)