Skip to content

Commit a99efca

Browse files
Merge pull request #29559 from nextcloud/feat/28139/profile-respect-user-enumeration
Respect user enumeration settings on profile
2 parents 52f8f4a + 3b91e4c commit a99efca

File tree

6 files changed

+203
-32
lines changed

6 files changed

+203
-32
lines changed

apps/files_sharing/tests/CapabilitiesTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
*/
2929
namespace OCA\Files_Sharing\Tests;
3030

31+
use OC\KnownUser\KnownUserService;
3132
use OC\Share20\Manager;
3233
use OCA\Files_Sharing\Capabilities;
3334
use OCP\EventDispatcher\IEventDispatcher;
@@ -94,7 +95,8 @@ private function getResults(array $map) {
9495
$this->createMock(IURLGenerator::class),
9596
$this->createMock(\OC_Defaults::class),
9697
$this->createMock(IEventDispatcher::class),
97-
$this->createMock(IUserSession::class)
98+
$this->createMock(IUserSession::class),
99+
$this->createMock(KnownUserService::class)
98100
);
99101
$cap = new Capabilities($config, $shareManager);
100102
$result = $this->getFilesSharingPart($cap->getCapabilities());

core/Controller/ProfilePageController.php

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,18 @@
2626

2727
namespace OC\Core\Controller;
2828

29+
use OC\KnownUser\KnownUserService;
30+
use OC\Profile\ProfileManager;
2931
use OCP\Accounts\IAccountManager;
3032
use OCP\AppFramework\Controller;
3133
use OCP\AppFramework\Http\TemplateResponse;
3234
use OCP\AppFramework\Services\IInitialState;
35+
use OCP\IGroupManager;
3336
use OCP\IRequest;
37+
use OCP\IUser;
3438
use OCP\IUserManager;
3539
use OCP\IUserSession;
36-
use OC\Profile\ProfileManager;
40+
use OCP\Share\IManager as IShareManager;
3741
use OCP\UserStatus\IManager as IUserStatusManager;
3842

3943
class ProfilePageController extends Controller {
@@ -48,6 +52,15 @@ class ProfilePageController extends Controller {
4852
/** @var ProfileManager */
4953
private $profileManager;
5054

55+
/** @var IShareManager */
56+
private $shareManager;
57+
58+
/** @var IGroupManager */
59+
private $groupManager;
60+
61+
/** @var KnownUserService */
62+
private $knownUserService;
63+
5164
/** @var IUserManager */
5265
private $userManager;
5366

@@ -63,6 +76,9 @@ public function __construct(
6376
IInitialState $initialStateService,
6477
IAccountManager $accountManager,
6578
ProfileManager $profileManager,
79+
IShareManager $shareManager,
80+
IGroupManager $groupManager,
81+
KnownUserService $knownUserService,
6682
IUserManager $userManager,
6783
IUserSession $userSession,
6884
IUserStatusManager $userStatusManager
@@ -71,6 +87,9 @@ public function __construct(
7187
$this->initialStateService = $initialStateService;
7288
$this->accountManager = $accountManager;
7389
$this->profileManager = $profileManager;
90+
$this->shareManager = $shareManager;
91+
$this->groupManager = $groupManager;
92+
$this->knownUserService = $knownUserService;
7493
$this->userManager = $userManager;
7594
$this->userSession = $userSession;
7695
$this->userStatusManager = $userStatusManager;
@@ -83,31 +102,34 @@ public function __construct(
83102
* @NoSubAdminRequired
84103
*/
85104
public function index(string $targetUserId): TemplateResponse {
86-
if (!$this->userManager->userExists($targetUserId)) {
87-
return new TemplateResponse(
88-
'core',
89-
'404-profile',
90-
[],
91-
TemplateResponse::RENDER_AS_GUEST,
92-
);
93-
}
105+
$profileNotFoundTemplate = new TemplateResponse(
106+
'core',
107+
'404-profile',
108+
[],
109+
TemplateResponse::RENDER_AS_GUEST,
110+
);
94111

95-
$visitingUser = $this->userSession->getUser();
96112
$targetUser = $this->userManager->get($targetUserId);
113+
if (!$targetUser instanceof IUser) {
114+
return $profileNotFoundTemplate;
115+
}
116+
$visitingUser = $this->userSession->getUser();
97117
$targetAccount = $this->accountManager->getAccount($targetUser);
98118

99119
if (!$this->isProfileEnabled($targetAccount)) {
100-
return new TemplateResponse(
101-
'core',
102-
'404-profile',
103-
[],
104-
TemplateResponse::RENDER_AS_GUEST,
105-
);
120+
return $profileNotFoundTemplate;
121+
}
122+
123+
// Run user enumeration checks only if viewing another user's profile
124+
if ($targetUser !== $visitingUser) {
125+
if (!$this->shareManager->currentUserCanEnumerateTargetUser($visitingUser, $targetUser)) {
126+
return $profileNotFoundTemplate;
127+
}
106128
}
107129

108130
$userStatuses = $this->userStatusManager->getUserStatuses([$targetUserId]);
109-
$status = array_shift($userStatuses);
110-
if (!empty($status)) {
131+
$status = $userStatuses[$targetUserId] ?? null;
132+
if ($status !== null) {
111133
$this->initialStateService->provideInitialState('status', [
112134
'icon' => $status->getIcon(),
113135
'message' => $status->getMessage(),

lib/private/Server.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,8 @@ public function __construct($webRoot, \OC\Config $config) {
12531253
$c->get(IURLGenerator::class),
12541254
$c->get('ThemingDefaults'),
12551255
$c->get(IEventDispatcher::class),
1256-
$c->get(IUserSession::class)
1256+
$c->get(IUserSession::class),
1257+
$c->get(KnownUserService::class)
12571258
);
12581259

12591260
return $manager;

lib/private/Share20/Manager.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
use OC\Cache\CappedMemoryCache;
4545
use OC\Files\Mount\MoveableMount;
46+
use OC\KnownUser\KnownUserService;
4647
use OC\Share20\Exception\ProviderException;
4748
use OCA\Files_Sharing\AppInfo\Application;
4849
use OCA\Files_Sharing\ISharedStorage;
@@ -118,7 +119,10 @@ class Manager implements IManager {
118119
private $defaults;
119120
/** @var IEventDispatcher */
120121
private $dispatcher;
122+
/** @var IUserSession */
121123
private $userSession;
124+
/** @var KnownUserService */
125+
private $knownUserService;
122126

123127
public function __construct(
124128
ILogger $logger,
@@ -137,7 +141,8 @@ public function __construct(
137141
IURLGenerator $urlGenerator,
138142
\OC_Defaults $defaults,
139143
IEventDispatcher $dispatcher,
140-
IUserSession $userSession
144+
IUserSession $userSession,
145+
KnownUserService $knownUserService
141146
) {
142147
$this->logger = $logger;
143148
$this->config = $config;
@@ -160,6 +165,7 @@ public function __construct(
160165
$this->defaults = $defaults;
161166
$this->dispatcher = $dispatcher;
162167
$this->userSession = $userSession;
168+
$this->knownUserService = $knownUserService;
163169
}
164170

165171
/**
@@ -1909,6 +1915,42 @@ public function allowEnumerationFullMatch(): bool {
19091915
return $this->config->getAppValue('core', 'shareapi_restrict_user_enumeration_full_match', 'yes') === 'yes';
19101916
}
19111917

1918+
public function currentUserCanEnumerateTargetUser(?IUser $currentUser, IUser $targetUser): bool {
1919+
if ($this->allowEnumerationFullMatch()) {
1920+
return true;
1921+
}
1922+
1923+
if (!$this->allowEnumeration()) {
1924+
return false;
1925+
}
1926+
1927+
if (!$this->limitEnumerationToPhone() && !$this->limitEnumerationToGroups()) {
1928+
// Enumeration is enabled and not restricted: OK
1929+
return true;
1930+
}
1931+
1932+
if (!$currentUser instanceof IUser) {
1933+
// Enumeration restrictions require an account
1934+
return false;
1935+
}
1936+
1937+
// Enumeration is limited to phone match
1938+
if ($this->limitEnumerationToPhone() && $this->knownUserService->isKnownToUser($currentUser->getUID(), $targetUser->getUID())) {
1939+
return true;
1940+
}
1941+
1942+
// Enumeration is limited to groups
1943+
if ($this->limitEnumerationToGroups()) {
1944+
$currentUserGroupIds = $this->groupManager->getUserGroupIds($currentUser);
1945+
$targetUserGroupIds = $this->groupManager->getUserGroupIds($targetUser);
1946+
if (!empty(array_intersect($currentUserGroupIds, $targetUserGroupIds))) {
1947+
return true;
1948+
}
1949+
}
1950+
1951+
return false;
1952+
}
1953+
19121954
/**
19131955
* Copied from \OC_Util::isSharingDisabledForUser
19141956
*

lib/public/Share/IManager.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use OCP\Files\Folder;
3333
use OCP\Files\Node;
3434

35+
use OCP\IUser;
3536
use OCP\Share\Exceptions\GenericShareException;
3637
use OCP\Share\Exceptions\ShareNotFound;
3738

@@ -447,6 +448,16 @@ public function limitEnumerationToPhone(): bool;
447448
*/
448449
public function allowEnumerationFullMatch(): bool;
449450

451+
/**
452+
* Check if the current user can enumerate the target user
453+
*
454+
* @param IUser|null $currentUser
455+
* @param IUser $targetUser
456+
* @return bool
457+
* @since 23.0.0
458+
*/
459+
public function currentUserCanEnumerateTargetUser(?IUser $currentUser, IUser $targetUser): bool;
460+
450461
/**
451462
* Check if sharing is disabled for the given user
452463
*

0 commit comments

Comments
 (0)