Skip to content

Commit

Permalink
feat(profilepicker): check fields visibility in reference provider
Browse files Browse the repository at this point in the history
Signed-off-by: Julien Veyssier <[email protected]>
  • Loading branch information
julien-nc committed Dec 17, 2024
1 parent 4fb561f commit cbc1051
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 20 deletions.
44 changes: 27 additions & 17 deletions lib/Reference/ProfilePickerReferenceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUserManager;
use OCP\Profile\IProfileManager;

class ProfilePickerReferenceProvider extends ADiscoverableReferenceProvider {
public const RICH_OBJECT_TYPE = 'users_picker_profile';
Expand All @@ -27,6 +28,7 @@ public function __construct(
private IURLGenerator $urlGenerator,
private IUserManager $userManager,
private IAccountManager $accountManager,
private IProfileManager $profileManager,
private ?string $userId,
) {
}
Expand Down Expand Up @@ -79,20 +81,30 @@ public function resolveReference(string $referenceText): ?IReference {
if ($user === null) {
return null;
}
$account = $this->accountManager->getAccount($user);
$profileEnabled = $account->getProperty(IAccountManager::PROPERTY_PROFILE_ENABLED)->getValue() === '1';
if (!$profileEnabled) {
if (!$this->profileManager->isProfileEnabled($user)) {
return null;
}
$account = $this->accountManager->getAccount($user);

$currentUser = $this->userManager->get($this->userId);

$reference = new Reference($referenceText);

$userDisplayName = $user->getDisplayName();
$userEmail = $user->getEMailAddress();
$userAvatarUrl = $this->urlGenerator->linkToRouteAbsolute('core.avatar.getAvatar', ['userId' => $userId, 'size' => '64']);

$bio = $account->getProperty(IAccountManager::PROPERTY_BIOGRAPHY);
$bio = $bio->getScope() !== IAccountManager::SCOPE_PRIVATE ? $bio->getValue() : null;
$bioProperty = $account->getProperty(IAccountManager::PROPERTY_BIOGRAPHY);
$bio = null;
$fullBio = null;
if ($this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_BIOGRAPHY, $user, $currentUser)) {
$fullBio = $bioProperty->getValue();
$bio = $fullBio !== ''
? (mb_strlen($fullBio) > 80
? (mb_substr($fullBio, 0, 80) . '...')
: $fullBio)
: null;
}
$headline = $account->getProperty(IAccountManager::PROPERTY_HEADLINE);
$location = $account->getProperty(IAccountManager::PROPERTY_ADDRESS);
$website = $account->getProperty(IAccountManager::PROPERTY_WEBSITE);
Expand All @@ -104,6 +116,8 @@ public function resolveReference(string $referenceText): ?IReference {
$reference->setDescription($userEmail ?? $userDisplayName);
$reference->setImageUrl($userAvatarUrl);

$isLocationVisible = $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_ADDRESS, $user, $currentUser);

// for the Vue reference widget
$reference->setRichObject(
self::RICH_OBJECT_TYPE,
Expand All @@ -112,18 +126,14 @@ public function resolveReference(string $referenceText): ?IReference {
'title' => $userDisplayName,
'subline' => $userEmail ?? $userDisplayName,
'email' => $userEmail,
'bio' => isset($bio) && $bio !== ''
? (mb_strlen($bio) > 80
? (mb_substr($bio, 0, 80) . '...')
: $bio)
: null,
'full_bio' => $bio,
'headline' => $headline->getScope() !== IAccountManager::SCOPE_PRIVATE ? $headline->getValue() : null,
'location' => $location->getScope() !== IAccountManager::SCOPE_PRIVATE ? $location->getValue() : null,
'location_url' => $location->getScope() !== IAccountManager::SCOPE_PRIVATE ? $this->getOpenStreetLocationUrl($location->getValue()) : null,
'website' => $website->getScope() !== IAccountManager::SCOPE_PRIVATE ? $website->getValue() : null,
'organisation' => $organisation->getScope() !== IAccountManager::SCOPE_PRIVATE ? $organisation->getValue() : null,
'role' => $role->getScope() !== IAccountManager::SCOPE_PRIVATE ? $role->getValue() : null,
'bio' => $bio,
'full_bio' => $fullBio,
'headline' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_HEADLINE, $user, $currentUser) ? $headline->getValue() : null,
'location' => $isLocationVisible ? $location->getValue() : null,
'location_url' => $isLocationVisible ? $this->getOpenStreetLocationUrl($location->getValue()) : null,
'website' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_WEBSITE, $user, $currentUser) ? $website->getValue() : null,
'organisation' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_ORGANISATION, $user, $currentUser) ? $organisation->getValue() : null,
'role' => $this->profileManager->isProfileFieldVisible(IAccountManager::PROPERTY_ROLE, $user, $currentUser) ? $role->getValue() : null,
'url' => $referenceText,
]
);
Expand Down
47 changes: 44 additions & 3 deletions tests/unit/Reference/ProfilePickerReferenceProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Profile\IProfileManager;
use PHPUnit\Framework\MockObject\MockObject;

class ProfilePickerReferenceProviderTest extends TestCase {
private string $userId = 'admin';
private IUser|MockObject $adminUser;
private IL10N|MockObject $l10n;
private IURLGenerator|MockObject $urlGenerator;
private IUserManager|MockObject $userManager;
private IAccountManager|MockObject $accountManager;
private IProfileManager|MockObject $profileManager;
private ProfilePickerReferenceProvider $referenceProvider;

private array $testUsersData = [
Expand All @@ -46,60 +49,74 @@ class ProfilePickerReferenceProviderTest extends TestCase {
'user1' => [
IAccountManager::PROPERTY_BIOGRAPHY => [
'scope' => IAccountManager::SCOPE_PRIVATE,
'visible' => true,
'value' => 'This is a first test user',
],
IAccountManager::PROPERTY_HEADLINE => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => false,
'value' => 'I\'m a first test user',
],
IAccountManager::PROPERTY_ADDRESS => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'Odessa',
],
IAccountManager::PROPERTY_WEBSITE => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'https://domain.co/testuser1',
],
IAccountManager::PROPERTY_ORGANISATION => [
'scope' => IAccountManager::SCOPE_PRIVATE,
'visible' => true,
'value' => 'Nextcloud GmbH',
],
IAccountManager::PROPERTY_ROLE => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'Non-existing user',
],
IAccountManager::PROPERTY_PROFILE_ENABLED => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => '1',
],
],
'user2' => [
IAccountManager::PROPERTY_BIOGRAPHY => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'This is a test user',
],
IAccountManager::PROPERTY_HEADLINE => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'Second test user',
],
IAccountManager::PROPERTY_ADDRESS => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'Berlin',
],
IAccountManager::PROPERTY_WEBSITE => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'https://domain.co/testuser2',
],
IAccountManager::PROPERTY_ORGANISATION => [
'scope' => IAccountManager::SCOPE_PRIVATE,
'visible' => true,
'value' => 'Nextcloud GmbH',
],
IAccountManager::PROPERTY_ROLE => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => 'Non-existing user',
],
IAccountManager::PROPERTY_PROFILE_ENABLED => [
'scope' => IAccountManager::SCOPE_LOCAL,
'visible' => true,
'value' => '1',
],
],
Expand All @@ -120,22 +137,40 @@ public function setUp(): void {
$this->urlGenerator = $this->createMock(IURLGenerator::class);
$this->userManager = $this->createMock(IUserManager::class);
$this->accountManager = $this->createMock(IAccountManager::class);
$this->profileManager = $this->createMock(IProfileManager::class);

$this->referenceProvider = new ProfilePickerReferenceProvider(
$this->l10n,
$this->urlGenerator,
$this->userManager,
$this->accountManager,
$this->profileManager,
$this->userId
);

$this->urlGenerator->expects($this->any())
->method('getBaseUrl')
->willReturn($this->baseUrl);

$this->profileManager->expects($this->any())
->method('isProfileFieldVisible')
->willReturnCallback(function (string $profileField, IUser $targetUser, ?IUser $visitingUser) {
return $this->testAccountsData[$targetUser->getUID()][$profileField]['visible']
&& $this->testAccountsData[$targetUser->getUID()][$profileField]['scope'] !== IAccountManager::SCOPE_PRIVATE;
});

$this->adminUser = $this->createMock(IUser::class);
$this->adminUser->expects($this->any())
->method('getUID')
->willReturn('admin');
$this->adminUser->expects($this->any())
->method('getDisplayName')
->willReturn('admin');
}

private function getTestAccountPropertyValue(string $testUserId, string $property): mixed {
if ($this->testAccountsData[$testUserId][$property]['scope'] === IAccountManager::SCOPE_PRIVATE) {
if (!$this->testAccountsData[$testUserId][$property]['visible']
|| $this->testAccountsData[$testUserId][$property]['scope'] === IAccountManager::SCOPE_PRIVATE) {
return null;
}
return $this->testAccountsData[$testUserId][$property]['value'];
Expand Down Expand Up @@ -163,8 +198,14 @@ private function setupUserAccountReferenceExpectation(string $userId): ?IReferen

$this->userManager->expects($this->any())
->method('get')
->with($userId)
->willReturn($user);
->willReturnCallback(function (string $uid) use ($user, $userId) {
if ($uid === $userId) {
return $user;
} elseif ($uid === 'admin') {
return $this->adminUser;
}
return null;
});

// setup account expectations
$account = $this->createMock(IAccount::class);
Expand Down

0 comments on commit cbc1051

Please sign in to comment.