Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 51 additions & 40 deletions lib/CurrentUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
class CurrentUser {

public function __construct(
protected IUserSession $userSession,
protected IRequest $request,
protected IManager $shareManager,
protected IFactory $l10nFactory,
protected readonly IUserSession $userSession,
protected readonly IRequest $request,
protected readonly IManager $shareManager,
protected readonly IFactory $l10nFactory,
) {
}

Expand All @@ -31,9 +31,8 @@ public function getUser(): ?IUser {

/**
* Get an identifier for the user, session or token
* @return string
*/
public function getUserIdentifier() {
public function getUserIdentifier(): string {
$uid = $this->getUID();
if ($uid !== null) {
return $uid;
Expand All @@ -55,9 +54,8 @@ public function getUserIdentifier() {

/**
* Get the current user id from the session
* @return string|null
*/
public function getUID() {
public function getUID(): ?string {
$user = $this->userSession->getUser();
if ($user instanceof IUser) {
return $user->getUID();
Expand All @@ -67,9 +65,8 @@ public function getUID() {

/**
* Get the current user cloud id from the session
* @return string|null
*/
public function getCloudId() {
public function getCloudId(): ?string {
$user = $this->userSession->getUser();
if ($user instanceof IUser) {
return $user->getCloudId();
Expand All @@ -82,43 +79,57 @@ public function getCloudId() {
* Check if the current request is via a public share link
*/
public function isPublicShareToken(): bool {
/** @psalm-suppress NoInterfaceProperties */
if (!empty($this->request->server['PHP_AUTH_USER'])) {
$token = $this->request->server['PHP_AUTH_USER'];
try {
$share = $this->shareManager->getShareByToken($token);
return $share->getShareType() === IShare::TYPE_LINK
|| $share->getShareType() === IShare::TYPE_EMAIL;
} catch (ShareNotFound $e) {
// No share found for this token
}
}

return false;
return $this->getPublicShare() !== null;
}

/**
* Get the cloud ID from the sharing token
* @return string|null
*/
protected function getCloudIDFromToken() {
protected function getCloudIDFromToken(): ?string {
$share = $this->getPublicShare();

if ($share === null || $share->getShareType() !== IShare::TYPE_REMOTE) {
return null;
}

return $share->getSharedWith();
}

protected function getPublicShare(): ?IShare {
if (basename($this->request->getScriptName()) !== 'public.php') {
return null;
}

$token = $this->getShareToken();
if ($token === null) {
return null;
}

try {
return $this->shareManager->getShareByToken($token);
} catch (ShareNotFound $e) {
return null;
}
}

protected function getShareToken(): ?string {
// The legacy public endpoint receive the share token in the HTTP basic auth header.
/** @psalm-suppress NoInterfaceProperties */
if (!empty($this->request->server['PHP_AUTH_USER'])) {
$token = $this->request->server['PHP_AUTH_USER'];
/**
* Until https://github.com/nextcloud/server/pull/26681 is merged
* @psalm-suppress InvalidCatch
*/
try {
$share = $this->shareManager->getShareByToken($token);
if ($share->getShareType() === IShare::TYPE_REMOTE) {
return $share->getSharedWith();
}
} catch (ShareNotFound $e) {
// No share, use the fallback
}
$authUser = (string)($this->request->server['PHP_AUTH_USER'] ?? '');
if ($authUser !== '') {
return $authUser;
}

return null;
// The current public endpoint receives the share token in the path.
// Copied from apps/dav/lib/Connector/Sabre/PublicAuth::getToken()
$path = $this->request->getPathInfo() ?: '';
// ['', 'dav', 'files', 'token']
$splittedPath = explode('/', $path);

if (count($splittedPath) < 4 || $splittedPath[3] === '') {
return null;
}

return $splittedPath[3];
}
}
8 changes: 5 additions & 3 deletions tests/CurrentUserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ protected function setUp(): void {
$this->userSession = $this->createMock(IUserSession::class);
$this->shareManager = $this->createMock(IManager::class);
$this->l10nFactory = $this->createMock(IFactory::class);

$this->request->method('getScriptName')->willReturn('/public.php');
}

protected function getInstance(array $methods = []): CurrentUser|MockObject {
Expand All @@ -83,13 +85,13 @@ protected function getInstance(array $methods = []): CurrentUser|MockObject {
public static function dataGetUserIdentifier(): array {
return [
[null, null, null, ''],
[null, 'uid', -1, 'uid'],
[null, 'uid', '-1', 'uid'],
[null, null, 'token', 'token'],
];
}

#[DataProvider('dataGetUserIdentifier')]
public function testGetUserIdentifier(?string $cachedIdentifier, string|int|null $uidResult, string|int|null $tokenResult, string $expected): void {
public function testGetUserIdentifier(?string $cachedIdentifier, string|int|null $uidResult, ?string $tokenResult, string $expected): void {
$instance = $this->getInstance([
'getUID',
'getCloudIDFromToken',
Expand All @@ -99,7 +101,7 @@ public function testGetUserIdentifier(?string $cachedIdentifier, string|int|null
->method('getUID')
->willReturn($uidResult);

$instance->expects($tokenResult !== -1 ? $this->once() : $this->never())
$instance->expects($tokenResult !== '-1' ? $this->once() : $this->never())
->method('getCloudIDFromToken')
->willReturn($tokenResult);

Expand Down
Loading