Skip to content

Commit 15fcb7f

Browse files
committed
fix(CurrentUser): Properly get share token from non-legacy public webdav
requests fix(CurrentUser): Properly get share token from non-legacy public webdav requests Signed-off-by: Louis Chmn <louis@chmn.me> Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Louis Chmn <louis@chmn.me>
1 parent d1f0aa6 commit 15fcb7f

2 files changed

Lines changed: 49 additions & 32 deletions

File tree

lib/CurrentUser.php

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -103,42 +103,57 @@ public function getCloudId(): string {
103103
* Check if the current request is via a public share link
104104
*/
105105
public function isPublicShareToken(): bool {
106-
/** @psalm-suppress NoInterfaceProperties */
107-
if (!empty($this->request->server['PHP_AUTH_USER'])) {
108-
$token = $this->request->server['PHP_AUTH_USER'];
109-
try {
110-
$share = $this->shareManager->getShareByToken($token);
111-
return $share->getShareType() === IShare::TYPE_LINK
112-
|| $share->getShareType() === IShare::TYPE_EMAIL;
113-
} catch (ShareNotFound $e) {
114-
// No share found for this token
115-
}
116-
}
117-
118-
return false;
106+
return $this->getPublicShare() !== null;
119107
}
120108

121109
/**
122110
* Get the cloud ID from the sharing token
123111
*/
124-
protected function getCloudIDFromToken() {
112+
protected function getCloudIDFromToken(): ?string {
113+
$share = $this->getPublicShare();
114+
115+
if ($share === null || $share->getShareType() !== IShare::TYPE_REMOTE) {
116+
return null;
117+
}
118+
119+
return $share->getSharedWith();
120+
}
121+
122+
protected function getPublicShare(): ?IShare {
123+
if (basename($this->request->getScriptName()) !== 'public.php') {
124+
return null;
125+
}
126+
127+
$token = $this->getShareToken();
128+
if ($token === null) {
129+
return null;
130+
}
131+
132+
try {
133+
return $this->shareManager->getShareByToken($token);
134+
} catch (ShareNotFound $e) {
135+
return null;
136+
}
137+
}
138+
139+
protected function getShareToken(): ?string {
140+
// The legacy public endpoint receive the share token in the HTTP basic auth header.
125141
/** @psalm-suppress NoInterfaceProperties */
126-
if (!empty($this->request->server['PHP_AUTH_USER'])) {
127-
$token = $this->request->server['PHP_AUTH_USER'];
128-
/**
129-
* Until https://github.com/nextcloud/server/pull/26681 is merged
130-
* @psalm-suppress InvalidCatch
131-
*/
132-
try {
133-
$share = $this->shareManager->getShareByToken($token);
134-
if ($share->getShareType() === IShare::TYPE_REMOTE) {
135-
return $share->getSharedWith();
136-
}
137-
} catch (ShareNotFound $e) {
138-
// No share, use the fallback
139-
}
142+
$authUser = (string)($this->request->server['PHP_AUTH_USER'] ?? '');
143+
if ($authUser !== '') {
144+
return $authUser;
145+
}
146+
147+
// The current public endpoint receives the share token in the path.
148+
// Copied from apps/dav/lib/Connector/Sabre/PublicAuth::getToken()
149+
$path = $this->request->getPathInfo() ?: '';
150+
// ['', 'dav', 'files', 'token']
151+
$splittedPath = explode('/', $path);
152+
153+
if (count($splittedPath) < 4 || $splittedPath[3] === '') {
154+
return null;
140155
}
141156

142-
return null;
157+
return $splittedPath[3];
143158
}
144159
}

tests/CurrentUserTest.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ protected function setUp(): void {
5757
$this->userSession = $this->createMock(IUserSession::class);
5858
$this->shareManager = $this->createMock(IManager::class);
5959
$this->l10nFactory = $this->createMock(IFactory::class);
60+
61+
$this->request->method('getScriptName')->willReturn('/public.php');
6062
}
6163

6264
protected function getInstance(array $methods = []): CurrentUser|MockObject {
@@ -83,14 +85,14 @@ protected function getInstance(array $methods = []): CurrentUser|MockObject {
8385
public static function dataGetUserIdentifier(): array {
8486
return [
8587
[null, null, null, ''],
86-
[null, 'uid', -1, 'uid'],
88+
[null, 'uid', '-1', 'uid'],
8789
[null, null, 'token', 'token'],
8890
['cached', -1, -1, 'cached'],
8991
];
9092
}
9193

9294
#[DataProvider('dataGetUserIdentifier')]
93-
public function testGetUserIdentifier(?string $cachedIdentifier, string|int|null $uidResult, string|int|null $tokenResult, string $expected): void {
95+
public function testGetUserIdentifier(?string $cachedIdentifier, string|int|null $uidResult, ?string $tokenResult, string $expected): void {
9496
$instance = $this->getInstance([
9597
'getUID',
9698
'getCloudIDFromToken',
@@ -102,7 +104,7 @@ public function testGetUserIdentifier(?string $cachedIdentifier, string|int|null
102104
->method('getUID')
103105
->willReturn($uidResult);
104106

105-
$instance->expects($tokenResult !== -1 ? $this->once() : $this->never())
107+
$instance->expects($tokenResult !== '-1' ? $this->once() : $this->never())
106108
->method('getCloudIDFromToken')
107109
->willReturn($tokenResult);
108110

0 commit comments

Comments
 (0)