mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
Merge 173a338f76 into d09b8c99de
This commit is contained in:
commit
58fc41f76b
13 changed files with 226 additions and 257 deletions
|
|
@ -770,33 +770,20 @@ class UsersController extends AUserDataOCSController {
|
|||
$targetUser = $currentLoggedInUser;
|
||||
}
|
||||
|
||||
$allowDisplayNameChange = $this->config->getSystemValue('allow_user_to_change_display_name', true);
|
||||
if ($allowDisplayNameChange === true && (
|
||||
$targetUser->getBackend() instanceof ISetDisplayNameBackend
|
||||
|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)
|
||||
)) {
|
||||
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
|
||||
foreach (IAccountManager::ALLOWED_PROPERTIES as $property) {
|
||||
if ($property === IAccountManager::PROPERTY_AVATAR) {
|
||||
continue;
|
||||
}
|
||||
if (!$targetUser->canEditProperty($property)) {
|
||||
continue;
|
||||
}
|
||||
$permittedFields[] = $property;
|
||||
}
|
||||
|
||||
// Fallback to display name value to avoid changing behavior with the new option.
|
||||
if ($this->config->getSystemValue('allow_user_to_change_email', $allowDisplayNameChange)) {
|
||||
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
|
||||
if ($targetUser->canEditProperty(IAccountManager::COLLECTION_EMAIL)) {
|
||||
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
|
||||
}
|
||||
|
||||
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BLUESKY;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_FEDIVERSE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ORGANISATION;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ROLE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_HEADLINE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS;
|
||||
|
||||
return new DataResponse($permittedFields);
|
||||
}
|
||||
|
||||
|
|
@ -841,7 +828,9 @@ class UsersController extends AUserDataOCSController {
|
|||
$permittedFields = [];
|
||||
if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
|
||||
// Editing self (display, email)
|
||||
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
|
||||
if ($targetUser->canEditProperty(IAccountManager::COLLECTION_EMAIL)) {
|
||||
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
|
||||
}
|
||||
$permittedFields[] = IAccountManager::COLLECTION_EMAIL . self::SCOPE_SUFFIX;
|
||||
} else {
|
||||
// Check if admin / subadmin
|
||||
|
|
@ -933,23 +922,10 @@ class UsersController extends AUserDataOCSController {
|
|||
|
||||
$permittedFields = [];
|
||||
if ($targetUser->getUID() === $currentLoggedInUser->getUID()) {
|
||||
$allowDisplayNameChange = $this->config->getSystemValue('allow_user_to_change_display_name', true);
|
||||
if ($allowDisplayNameChange !== false && (
|
||||
$targetUser->getBackend() instanceof ISetDisplayNameBackend
|
||||
|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)
|
||||
)) {
|
||||
if ($targetUser->canChangeDisplayName()) {
|
||||
$permittedFields[] = self::USER_FIELD_DISPLAYNAME;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
|
||||
}
|
||||
|
||||
// Fallback to display name value to avoid changing behavior with the new option.
|
||||
if ($this->config->getSystemValue('allow_user_to_change_email', $allowDisplayNameChange)) {
|
||||
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
|
||||
}
|
||||
|
||||
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX;
|
||||
|
||||
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
|
||||
|
||||
$permittedFields[] = self::USER_FIELD_PASSWORD;
|
||||
|
|
@ -972,34 +948,16 @@ class UsersController extends AUserDataOCSController {
|
|||
$permittedFields[] = self::USER_FIELD_FIRST_DAY_OF_WEEK;
|
||||
}
|
||||
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BLUESKY;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_FEDIVERSE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ORGANISATION;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ROLE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_HEADLINE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BIRTHDATE;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS;
|
||||
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BLUESKY . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_FEDIVERSE . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ORGANISATION . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_ROLE . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_HEADLINE . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BIOGRAPHY . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_BIRTHDATE . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX;
|
||||
$permittedFields[] = IAccountManager::PROPERTY_PRONOUNS . self::SCOPE_SUFFIX;
|
||||
foreach (IAccountManager::ALLOWED_PROPERTIES as $property) {
|
||||
$permittedFields[] = $property . self::SCOPE_SUFFIX;
|
||||
if ($property === IAccountManager::PROPERTY_AVATAR) {
|
||||
continue;
|
||||
}
|
||||
if (!$targetUser->canEditProperty($property)) {
|
||||
continue;
|
||||
}
|
||||
$permittedFields[] = $property;
|
||||
}
|
||||
|
||||
// If admin they can edit their own quota and manager
|
||||
$isAdmin = $this->groupManager->isAdmin($currentLoggedInUser->getUID());
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ use OCP\L10N\IFactory;
|
|||
use OCP\Mail\IEMailTemplate;
|
||||
use OCP\Security\Events\GenerateSecurePasswordEvent;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OCP\User\Backend\ISetDisplayNameBackend;
|
||||
use OCP\UserInterface;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
|
@ -1635,6 +1634,10 @@ class UsersControllerTest extends TestCase {
|
|||
$targetUser = $this->getMockBuilder(IUser::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$targetUser
|
||||
->expects($this->once())
|
||||
->method('canChangeDisplayName')
|
||||
->willReturn(true);
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('getUser')
|
||||
|
|
@ -1644,10 +1647,6 @@ class UsersControllerTest extends TestCase {
|
|||
->method('get')
|
||||
->with('UserToEdit')
|
||||
->willReturn($targetUser);
|
||||
$targetUser
|
||||
->expects($this->once())
|
||||
->method('getBackend')
|
||||
->willReturn($this->createMock(ISetDisplayNameBackend::class));
|
||||
$targetUser
|
||||
->expects($this->once())
|
||||
->method('setDisplayName')
|
||||
|
|
@ -1672,6 +1671,14 @@ class UsersControllerTest extends TestCase {
|
|||
$targetUser = $this->getMockBuilder(IUser::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$targetUser
|
||||
->expects($this->atLeastOnce())
|
||||
->method('canEditProperty')
|
||||
->willReturnCallback(
|
||||
fn (string $property): bool => match($property) {
|
||||
IAccountManager::PROPERTY_EMAIL => true,
|
||||
default => false,
|
||||
});
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('getUser')
|
||||
|
|
@ -1690,12 +1697,6 @@ class UsersControllerTest extends TestCase {
|
|||
->method('getUID')
|
||||
->willReturn('UID');
|
||||
|
||||
$backend = $this->createMock(UserInterface::class);
|
||||
$targetUser
|
||||
->expects($this->any())
|
||||
->method('getBackend')
|
||||
->willReturn($backend);
|
||||
|
||||
$this->config->method('getSystemValue')->willReturnCallback(fn (string $key, mixed $default) => $default);
|
||||
|
||||
$this->assertEquals([], $this->api->editUser('UserToEdit', 'email', 'demo@nextcloud.com')->getData());
|
||||
|
|
@ -1726,12 +1727,6 @@ class UsersControllerTest extends TestCase {
|
|||
->method('getUID')
|
||||
->willReturn('UID');
|
||||
|
||||
$backend = $this->createMock(UserInterface::class);
|
||||
$targetUser
|
||||
->expects($this->any())
|
||||
->method('getBackend')
|
||||
->willReturn($backend);
|
||||
|
||||
$userAccount = $this->createMock(IAccount::class);
|
||||
|
||||
$this->accountManager
|
||||
|
|
@ -1772,11 +1767,6 @@ class UsersControllerTest extends TestCase {
|
|||
->method('getUID')
|
||||
->willReturn('UID');
|
||||
|
||||
$backend = $this->createMock(UserInterface::class);
|
||||
$targetUser
|
||||
->expects($this->any())
|
||||
->method('getBackend')
|
||||
->willReturn($backend);
|
||||
$targetUser
|
||||
->expects($this->any())
|
||||
->method('getSystemEMailAddress')
|
||||
|
|
@ -1824,12 +1814,6 @@ class UsersControllerTest extends TestCase {
|
|||
->method('getUID')
|
||||
->willReturn('UID');
|
||||
|
||||
$backend = $this->createMock(UserInterface::class);
|
||||
$targetUser
|
||||
->expects($this->any())
|
||||
->method('getBackend')
|
||||
->willReturn($backend);
|
||||
|
||||
$property = $this->createMock(IAccountProperty::class);
|
||||
$property->method('getValue')
|
||||
->willReturn('demo1@nextcloud.com');
|
||||
|
|
@ -1886,11 +1870,14 @@ class UsersControllerTest extends TestCase {
|
|||
->method('getUID')
|
||||
->willReturn('UID');
|
||||
|
||||
$backend = $this->createMock(UserInterface::class);
|
||||
$targetUser
|
||||
->expects($this->any())
|
||||
->method('getBackend')
|
||||
->willReturn($backend);
|
||||
->expects($this->atLeastOnce())
|
||||
->method('canEditProperty')
|
||||
->willReturnCallback(
|
||||
fn (string $property): bool => match($property) {
|
||||
IAccountManager::PROPERTY_EMAIL => true,
|
||||
default => false,
|
||||
});
|
||||
|
||||
$this->config->method('getSystemValue')->willReturnCallback(fn (string $key, mixed $default) => $default);
|
||||
|
||||
|
|
@ -1923,6 +1910,14 @@ class UsersControllerTest extends TestCase {
|
|||
->expects($this->any())
|
||||
->method('getUID')
|
||||
->willReturn('UID');
|
||||
$loggedInUser
|
||||
->expects($this->atLeastOnce())
|
||||
->method('canEditProperty')
|
||||
->willReturnCallback(
|
||||
fn (string $property): bool => match($property) {
|
||||
$propertyName => true,
|
||||
default => false,
|
||||
});
|
||||
$this->userSession
|
||||
->expects($this->once())
|
||||
->method('getUser')
|
||||
|
|
@ -4290,137 +4285,79 @@ class UsersControllerTest extends TestCase {
|
|||
|
||||
public static function dataGetEditableFields(): array {
|
||||
return [
|
||||
[false, true, ISetDisplayNameBackend::class, [
|
||||
[false, true, [
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_BIRTHDATE,
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
]],
|
||||
[true, false, ISetDisplayNameBackend::class, [
|
||||
[true, false, [
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_BIRTHDATE,
|
||||
IAccountManager::PROPERTY_DISPLAYNAME,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
]],
|
||||
[true, true, ISetDisplayNameBackend::class, [
|
||||
[true, true, [
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_BIRTHDATE,
|
||||
IAccountManager::PROPERTY_DISPLAYNAME,
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
]],
|
||||
[false, false, ISetDisplayNameBackend::class, [
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
[false, false, [
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_BIRTHDATE,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
]],
|
||||
[false, true, UserInterface::class, [
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
]],
|
||||
[true, false, UserInterface::class, [
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
]],
|
||||
[true, true, UserInterface::class, [
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
]],
|
||||
[false, false, UserInterface::class, [
|
||||
IAccountManager::COLLECTION_EMAIL,
|
||||
IAccountManager::PROPERTY_PHONE,
|
||||
IAccountManager::PROPERTY_ADDRESS,
|
||||
IAccountManager::PROPERTY_WEBSITE,
|
||||
IAccountManager::PROPERTY_TWITTER,
|
||||
IAccountManager::PROPERTY_BLUESKY,
|
||||
IAccountManager::PROPERTY_FEDIVERSE,
|
||||
IAccountManager::PROPERTY_ORGANISATION,
|
||||
IAccountManager::PROPERTY_ROLE,
|
||||
IAccountManager::PROPERTY_HEADLINE,
|
||||
IAccountManager::PROPERTY_BIOGRAPHY,
|
||||
IAccountManager::PROPERTY_PROFILE_ENABLED,
|
||||
IAccountManager::PROPERTY_PRONOUNS,
|
||||
]],
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'dataGetEditableFields')]
|
||||
public function testGetEditableFields(bool $allowedToChangeDisplayName, bool $allowedToChangeEmail, string $userBackend, array $expected): void {
|
||||
public function testGetEditableFields(bool $allowedToChangeDisplayName, bool $allowedToChangeEmail, array $expected): void {
|
||||
$this->config->method('getSystemValue')->willReturnCallback(fn (string $key, mixed $default) => match ($key) {
|
||||
'allow_user_to_change_display_name' => $allowedToChangeDisplayName,
|
||||
'allow_user_to_change_email' => $allowedToChangeEmail,
|
||||
|
|
@ -4431,12 +4368,16 @@ class UsersControllerTest extends TestCase {
|
|||
$this->userSession->method('getUser')
|
||||
->willReturn($user);
|
||||
|
||||
$backend = $this->createMock($userBackend);
|
||||
|
||||
$user->method('getUID')
|
||||
->willReturn('userId');
|
||||
$user->method('getBackend')
|
||||
->willReturn($backend);
|
||||
$user->method('canEditProperty')
|
||||
->willReturnCallback(
|
||||
fn (string $property): bool => match($property) {
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => $allowedToChangeDisplayName,
|
||||
IAccountManager::PROPERTY_EMAIL => $allowedToChangeEmail,
|
||||
default => true,
|
||||
}
|
||||
);
|
||||
|
||||
$expectedResp = new DataResponse($expected);
|
||||
$this->assertEquals($expectedResp, $this->api->getEditableFields('userId'));
|
||||
|
|
|
|||
|
|
@ -422,10 +422,8 @@ class UsersController extends Controller {
|
|||
IAccountManager::PROPERTY_BIRTHDATE => ['value' => $birthdate, 'scope' => $birthdateScope],
|
||||
IAccountManager::PROPERTY_PRONOUNS => ['value' => $pronouns, 'scope' => $pronounsScope],
|
||||
];
|
||||
$allowUserToChangeDisplayName = $this->config->getSystemValueBool('allow_user_to_change_display_name', true);
|
||||
foreach ($updatable as $property => $data) {
|
||||
if ($allowUserToChangeDisplayName === false
|
||||
&& in_array($property, [IAccountManager::PROPERTY_DISPLAYNAME, IAccountManager::PROPERTY_EMAIL], true)) {
|
||||
if (!$user->canEditProperty($property)) {
|
||||
continue;
|
||||
}
|
||||
$property = $userAccount->getProperty($property);
|
||||
|
|
|
|||
|
|
@ -337,6 +337,16 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$user = $this->createMock(IUser::class);
|
||||
$user->method('getUID')->willReturn('johndoe');
|
||||
|
||||
$user->expects($this->atLeastOnce())
|
||||
->method('canEditProperty')
|
||||
->willReturnCallback(
|
||||
fn (string $property): bool => match($property) {
|
||||
IAccountManager::PROPERTY_EMAIL,
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => false,
|
||||
default => true,
|
||||
}
|
||||
);
|
||||
|
||||
$this->userSession->method('getUser')->willReturn($user);
|
||||
|
||||
/** @var MockObject|IAccount $userAccount */
|
||||
|
|
@ -378,11 +388,6 @@ class UsersControllerTest extends \Test\TestCase {
|
|||
$emailProperty->expects($this->never())
|
||||
->method('setScope');
|
||||
|
||||
$this->config->expects($this->once())
|
||||
->method('getSystemValueBool')
|
||||
->with('allow_user_to_change_display_name')
|
||||
->willReturn(false);
|
||||
|
||||
$this->appManager->expects($this->any())
|
||||
->method('isEnabledForUser')
|
||||
->with('federatedfilesharing')
|
||||
|
|
|
|||
|
|
@ -14,15 +14,17 @@ use OCA\User_LDAP\Exceptions\NotOnLDAP;
|
|||
use OCA\User_LDAP\User\DeletedUsersIndex;
|
||||
use OCA\User_LDAP\User\OfflineUser;
|
||||
use OCA\User_LDAP\User\User;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\IUserBackend;
|
||||
use OCP\Notification\IManager as INotificationManager;
|
||||
use OCP\User\Backend\ICountMappedUsersBackend;
|
||||
use OCP\User\Backend\ILimitAwareCountUsersBackend;
|
||||
use OCP\User\Backend\IPropertyPermissionBackend;
|
||||
use OCP\User\Backend\IProvideEnabledStateBackend;
|
||||
use OCP\UserInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend {
|
||||
class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IPropertyPermissionBackend {
|
||||
public function __construct(
|
||||
Access $access,
|
||||
protected INotificationManager $notificationManager,
|
||||
|
|
@ -643,4 +645,23 @@ class User_LDAP extends BackendUtility implements IUserBackend, UserInterface, I
|
|||
public function getDisabledUserList(?int $limit = null, int $offset = 0, string $search = ''): array {
|
||||
throw new \Exception('This is implemented directly in User_Proxy');
|
||||
}
|
||||
|
||||
public function canEditProperty(string $uid, string $property): bool {
|
||||
return match($property) {
|
||||
// Display name is always set by LDAP
|
||||
IAccountManager::PROPERTY_DISPLAYNAME => false,
|
||||
IAccountManager::PROPERTY_EMAIL => ((string)$this->access->connection->ldapEmailAttribute !== ''),
|
||||
IAccountManager::PROPERTY_PHONE => ((string)$this->access->connection->ldapAttributePhone !== ''),
|
||||
IAccountManager::PROPERTY_WEBSITE => ((string)$this->access->connection->ldapAttributeWebsite !== ''),
|
||||
IAccountManager::PROPERTY_ADDRESS => ((string)$this->access->connection->ldapAttributeAddress !== ''),
|
||||
IAccountManager::PROPERTY_FEDIVERSE => ((string)$this->access->connection->ldapAttributeFediverse !== ''),
|
||||
IAccountManager::PROPERTY_ORGANISATION => ((string)$this->access->connection->ldapAttributeOrganisation !== ''),
|
||||
IAccountManager::PROPERTY_ROLE => ((string)$this->access->connection->ldapAttributeRole !== ''),
|
||||
IAccountManager::PROPERTY_HEADLINE => ((string)$this->access->connection->ldapAttributeHeadline !== ''),
|
||||
IAccountManager::PROPERTY_BIOGRAPHY => ((string)$this->access->connection->ldapAttributeBiography !== ''),
|
||||
IAccountManager::PROPERTY_BIRTHDATE => ((string)$this->access->connection->ldapAttributeBirthDate !== ''),
|
||||
IAccountManager::PROPERTY_PRONOUNS => ((string)$this->access->connection->ldapAttributePronouns !== ''),
|
||||
default => true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use OCP\Notification\IManager as INotificationManager;
|
|||
use OCP\User\Backend\ICountMappedUsersBackend;
|
||||
use OCP\User\Backend\IGetDisplayNameBackend;
|
||||
use OCP\User\Backend\ILimitAwareCountUsersBackend;
|
||||
use OCP\User\Backend\IPropertyPermissionBackend;
|
||||
use OCP\User\Backend\IProvideEnabledStateBackend;
|
||||
use OCP\UserInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
|
@ -22,7 +23,7 @@ use Psr\Log\LoggerInterface;
|
|||
/**
|
||||
* @template-extends Proxy<User_LDAP>
|
||||
*/
|
||||
class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IGetDisplayNameBackend {
|
||||
class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP, ILimitAwareCountUsersBackend, ICountMappedUsersBackend, IProvideEnabledStateBackend, IGetDisplayNameBackend, IPropertyPermissionBackend {
|
||||
public function __construct(
|
||||
private Helper $helper,
|
||||
ILDAPWrapper $ldap,
|
||||
|
|
@ -432,4 +433,8 @@ class User_Proxy extends Proxy implements IUserBackend, UserInterface, IUserLDAP
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function canEditProperty(string $uid, string $property): bool {
|
||||
return $this->handleRequest($uid, 'canEditProperty', [$uid, $property]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2135,9 +2135,6 @@
|
|||
<code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code>
|
||||
<code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code>
|
||||
<code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code>
|
||||
<code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code>
|
||||
<code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code>
|
||||
<code><![CDATA[IAccountManager::PROPERTY_TWITTER]]></code>
|
||||
</DeprecatedConstant>
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[deleteUserValue]]></code>
|
||||
|
|
@ -2148,8 +2145,6 @@
|
|||
<code><![CDATA[getAppValue]]></code>
|
||||
<code><![CDATA[getUserValue]]></code>
|
||||
<code><![CDATA[implementsActions]]></code>
|
||||
<code><![CDATA[implementsActions]]></code>
|
||||
<code><![CDATA[implementsActions]]></code>
|
||||
<code><![CDATA[search]]></code>
|
||||
<code><![CDATA[search]]></code>
|
||||
<code><![CDATA[setUserValue]]></code>
|
||||
|
|
@ -2498,8 +2493,6 @@
|
|||
<file src="apps/theming/lib/Controller/ThemingController.php">
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[getAppValue]]></code>
|
||||
<code><![CDATA[getAppValue]]></code>
|
||||
<code><![CDATA[getAppValue]]></code>
|
||||
</DeprecatedMethod>
|
||||
</file>
|
||||
<file src="apps/theming/lib/Controller/UserThemeController.php">
|
||||
|
|
|
|||
|
|
@ -1013,6 +1013,7 @@ return array(
|
|||
'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => $baseDir . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php',
|
||||
'OCP\\User\\Backend\\IPasswordConfirmationBackend' => $baseDir . '/lib/public/User/Backend/IPasswordConfirmationBackend.php',
|
||||
'OCP\\User\\Backend\\IPasswordHashBackend' => $baseDir . '/lib/public/User/Backend/IPasswordHashBackend.php',
|
||||
'OCP\\User\\Backend\\IPropertyPermissionBackend' => $baseDir . '/lib/public/User/Backend/IPropertyPermissionBackend.php',
|
||||
'OCP\\User\\Backend\\IProvideAvatarBackend' => $baseDir . '/lib/public/User/Backend/IProvideAvatarBackend.php',
|
||||
'OCP\\User\\Backend\\IProvideEnabledStateBackend' => $baseDir . '/lib/public/User/Backend/IProvideEnabledStateBackend.php',
|
||||
'OCP\\User\\Backend\\ISearchKnownUsersBackend' => $baseDir . '/lib/public/User/Backend/ISearchKnownUsersBackend.php',
|
||||
|
|
|
|||
|
|
@ -1054,6 +1054,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\User\\Backend\\ILimitAwareCountUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ILimitAwareCountUsersBackend.php',
|
||||
'OCP\\User\\Backend\\IPasswordConfirmationBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordConfirmationBackend.php',
|
||||
'OCP\\User\\Backend\\IPasswordHashBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPasswordHashBackend.php',
|
||||
'OCP\\User\\Backend\\IPropertyPermissionBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IPropertyPermissionBackend.php',
|
||||
'OCP\\User\\Backend\\IProvideAvatarBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideAvatarBackend.php',
|
||||
'OCP\\User\\Backend\\IProvideEnabledStateBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/IProvideEnabledStateBackend.php',
|
||||
'OCP\\User\\Backend\\ISearchKnownUsersBackend' => __DIR__ . '/../../..' . '/lib/public/User/Backend/ISearchKnownUsersBackend.php',
|
||||
|
|
|
|||
|
|
@ -100,15 +100,15 @@ class LazyUser implements IUser {
|
|||
return $this->getUser()->getBackend();
|
||||
}
|
||||
|
||||
public function canChangeAvatar() {
|
||||
public function canChangeAvatar(): bool {
|
||||
return $this->getUser()->canChangeAvatar();
|
||||
}
|
||||
|
||||
public function canChangePassword() {
|
||||
public function canChangePassword(): bool {
|
||||
return $this->getUser()->canChangePassword();
|
||||
}
|
||||
|
||||
public function canChangeDisplayName() {
|
||||
public function canChangeDisplayName(): bool {
|
||||
return $this->getUser()->canChangeDisplayName();
|
||||
}
|
||||
|
||||
|
|
@ -116,6 +116,10 @@ class LazyUser implements IUser {
|
|||
return $this->getUser()->canChangeEmail();
|
||||
}
|
||||
|
||||
public function canEditProperty(string $property): bool {
|
||||
return $this->getUser()->canEditProperty($property);
|
||||
}
|
||||
|
||||
public function isEnabled() {
|
||||
return $this->getUser()->isEnabled();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use OCP\IUserBackend;
|
|||
use OCP\Notification\IManager as INotificationManager;
|
||||
use OCP\User\Backend\IGetHomeBackend;
|
||||
use OCP\User\Backend\IPasswordHashBackend;
|
||||
use OCP\User\Backend\IPropertyPermissionBackend;
|
||||
use OCP\User\Backend\IProvideAvatarBackend;
|
||||
use OCP\User\Backend\IProvideEnabledStateBackend;
|
||||
use OCP\User\Backend\ISetDisplayNameBackend;
|
||||
|
|
@ -413,44 +414,50 @@ class User implements IUser {
|
|||
return $this->backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the backend allows the user to change their avatar on Personal page
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canChangeAvatar() {
|
||||
if ($this->backend instanceof IProvideAvatarBackend || $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
|
||||
/** @var IProvideAvatarBackend $backend */
|
||||
$backend = $this->backend;
|
||||
return $backend->canChangeAvatar($this->uid);
|
||||
}
|
||||
return true;
|
||||
public function canChangeAvatar(): bool {
|
||||
return $this->canEditProperty(IAccountManager::PROPERTY_AVATAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the backend supports changing passwords
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canChangePassword() {
|
||||
public function canChangePassword(): bool {
|
||||
return $this->backend->implementsActions(Backend::SET_PASSWORD);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the backend supports changing display names
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canChangeDisplayName() {
|
||||
if (!$this->config->getSystemValueBool('allow_user_to_change_display_name', true)) {
|
||||
return false;
|
||||
}
|
||||
return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
|
||||
public function canChangeDisplayName(): bool {
|
||||
return $this->canEditProperty(IAccountManager::PROPERTY_DISPLAYNAME);
|
||||
}
|
||||
|
||||
public function canChangeEmail(): bool {
|
||||
// Fallback to display name value to avoid changing behavior with the new option.
|
||||
return $this->config->getSystemValueBool('allow_user_to_change_email', $this->config->getSystemValueBool('allow_user_to_change_display_name', true));
|
||||
return $this->canEditProperty(IAccountManager::PROPERTY_EMAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IAccountManager::PROPERTY_*|IAccountManager::COLLECTION_* $property
|
||||
*/
|
||||
public function canEditProperty(string $property): bool {
|
||||
if ($this->backend instanceof IPropertyPermissionBackend) {
|
||||
$permission = $this->backend->canEditProperty($this->uid, $property);
|
||||
if (!$permission) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch ($property) {
|
||||
case IAccountManager::PROPERTY_DISPLAYNAME:
|
||||
if (!$this->config->getSystemValueBool('allow_user_to_change_display_name', true)) {
|
||||
return false;
|
||||
}
|
||||
return $this->backend->implementsActions(Backend::SET_DISPLAYNAME);
|
||||
case IAccountManager::PROPERTY_AVATAR:
|
||||
if ($this->backend instanceof IProvideAvatarBackend || $this->backend->implementsActions(Backend::PROVIDE_AVATAR)) {
|
||||
/** @var IProvideAvatarBackend $backend */
|
||||
$backend = $this->backend;
|
||||
return $backend->canChangeAvatar($this->uid);
|
||||
}
|
||||
return true;
|
||||
case IAccountManager::PROPERTY_EMAIL:
|
||||
return $this->config->getSystemValueBool('allow_user_to_change_email', $this->config->getSystemValueBool('allow_user_to_change_display_name', true));
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -8,12 +8,15 @@
|
|||
namespace OCP;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\AppFramework\Attribute\Consumable;
|
||||
|
||||
/**
|
||||
* Interface IUser
|
||||
*
|
||||
* @since 8.0.0
|
||||
*/
|
||||
#[Consumable(since: '8.0.0')]
|
||||
interface IUser {
|
||||
/**
|
||||
* @since 32.0.0
|
||||
|
|
@ -133,26 +136,23 @@ interface IUser {
|
|||
/**
|
||||
* check if the backend allows the user to change their avatar on Personal page
|
||||
*
|
||||
* @return bool
|
||||
* @since 8.0.0
|
||||
*/
|
||||
public function canChangeAvatar();
|
||||
public function canChangeAvatar(): bool;
|
||||
|
||||
/**
|
||||
* check if the backend supports changing passwords
|
||||
*
|
||||
* @return bool
|
||||
* @since 8.0.0
|
||||
*/
|
||||
public function canChangePassword();
|
||||
public function canChangePassword(): bool;
|
||||
|
||||
/**
|
||||
* check if the backend supports changing display names
|
||||
*
|
||||
* @return bool
|
||||
* @since 8.0.0
|
||||
*/
|
||||
public function canChangeDisplayName();
|
||||
public function canChangeDisplayName(): bool;
|
||||
|
||||
/**
|
||||
* Check if the backend supports changing email
|
||||
|
|
@ -161,6 +161,12 @@ interface IUser {
|
|||
*/
|
||||
public function canChangeEmail(): bool;
|
||||
|
||||
/**
|
||||
* @param IAccountManager::PROPERTY_*|IAccountManager::COLLECTION_* $property
|
||||
* @since 34.0.0
|
||||
*/
|
||||
public function canEditProperty(string $property): bool;
|
||||
|
||||
/**
|
||||
* check if the user is enabled
|
||||
*
|
||||
|
|
|
|||
29
lib/public/User/Backend/IPropertyPermissionBackend.php
Normal file
29
lib/public/User/Backend/IPropertyPermissionBackend.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCP\User\Backend;
|
||||
|
||||
use OCP\Accounts\IAccountManager;
|
||||
use OCP\AppFramework\Attribute\Consumable;
|
||||
use OCP\AppFramework\Attribute\Implementable;
|
||||
|
||||
/**
|
||||
* @since 34.0.0
|
||||
*/
|
||||
#[Implementable(since: '34.0.0')]
|
||||
#[Consumable(since: '34.0.0')]
|
||||
interface IPropertyPermissionBackend {
|
||||
/**
|
||||
* @since 34.0.0
|
||||
*
|
||||
* @param IAccountManager::PROPERTY_*|IAccountManager::COLLECTION_* $property
|
||||
* @return bool Whether the user is allowed to edit its own property
|
||||
*/
|
||||
public function canEditProperty(string $uid, string $property): bool;
|
||||
}
|
||||
Loading…
Reference in a new issue