Skip to content

Commit e89971d

Browse files
feat(users): Store and load a user's manager
Co-Authored-By: hamza221 <hamzamahjoubi221@gmail.com> Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
1 parent 1399c88 commit e89971d

19 files changed

+270
-19
lines changed

apps/dav/lib/CardDAV/Converter.php

+19-1
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@
3131
use OCP\Accounts\IAccountManager;
3232
use OCP\IImage;
3333
use OCP\IUser;
34+
use OCP\IUserManager;
3435
use Sabre\VObject\Component\VCard;
3536
use Sabre\VObject\Property\Text;
3637

3738
class Converter {
3839
/** @var IAccountManager */
3940
private $accountManager;
41+
private IUserManager $userManager;
4042

41-
public function __construct(IAccountManager $accountManager) {
43+
public function __construct(IAccountManager $accountManager,
44+
IUserManager $userManager) {
4245
$this->accountManager = $accountManager;
46+
$this->userManager = $userManager;
4347
}
4448

4549
public function createCardFromUser(IUser $user): ?VCard {
@@ -102,6 +106,20 @@ public function createCardFromUser(IUser $user): ?VCard {
102106
}
103107
}
104108

109+
// Local properties
110+
$managers = $user->getManagerUids();
111+
// X-MANAGERSNAME only allows a single value, so we take the first manager
112+
if (isset($managers[0])) {
113+
$displayName = $this->userManager->getDisplayName($managers[0]);
114+
// Only set the manager if a user object is found
115+
if ($displayName !== null) {
116+
$vCard->add(new Text($vCard, 'X-MANAGERSNAME', $displayName, [
117+
'uid' => $managers[0],
118+
'X-NC-SCOPE' => IAccountManager::SCOPE_LOCAL,
119+
]));
120+
}
121+
}
122+
105123
if ($publish && !empty($cloudId)) {
106124
$vCard->add(new Text($vCard, 'CLOUD', $cloudId));
107125
$vCard->validate();

apps/dav/tests/unit/CardDAV/ConverterTest.php

+32-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<?php
2+
3+
declare(strict_types=1);
4+
25
/**
36
* @copyright Copyright (c) 2016, ownCloud, Inc.
47
*
@@ -33,18 +36,22 @@
3336
use OCP\Accounts\IAccountProperty;
3437
use OCP\IImage;
3538
use OCP\IUser;
39+
use OCP\IUserManager;
3640
use PHPUnit\Framework\MockObject\MockObject;
3741
use Test\TestCase;
3842

3943
class ConverterTest extends TestCase {
4044

4145
/** @var IAccountManager|\PHPUnit\Framework\MockObject\MockObject */
4246
private $accountManager;
47+
/** @var IUserManager|(IUserManager&MockObject)|MockObject */
48+
private IUserManager|MockObject $userManager;
4349

4450
protected function setUp(): void {
4551
parent::setUp();
4652

4753
$this->accountManager = $this->createMock(IAccountManager::class);
54+
$this->userManager = $this->createMock(IUserManager::class);
4855
}
4956

5057
/**
@@ -96,7 +103,7 @@ public function testCreation($expectedVCard, $displayName = null, $eMailAddress
96103
$user = $this->getUserMock((string)$displayName, $eMailAddress, $cloudId);
97104
$accountManager = $this->getAccountManager($user);
98105

99-
$converter = new Converter($accountManager);
106+
$converter = new Converter($accountManager, $this->userManager);
100107
$vCard = $converter->createCardFromUser($user);
101108
if ($expectedVCard !== null) {
102109
$this->assertInstanceOf('Sabre\VObject\Component\VCard', $vCard);
@@ -107,6 +114,29 @@ public function testCreation($expectedVCard, $displayName = null, $eMailAddress
107114
}
108115
}
109116

117+
public function testManagerProp(): void {
118+
$user = $this->getUserMock("user", "user@domain.tld", "user@cloud.domain.tld");
119+
$user->method('getManagerUids')
120+
->willReturn(['mgr']);
121+
$this->userManager->expects(self::once())
122+
->method('getDisplayName')
123+
->with('mgr')
124+
->willReturn('Manager');
125+
$accountManager = $this->getAccountManager($user);
126+
127+
$converter = new Converter($accountManager, $this->userManager);
128+
$vCard = $converter->createCardFromUser($user);
129+
130+
$this->compareData(
131+
[
132+
'cloud' => 'user@cloud.domain.tld',
133+
'email' => 'user@domain.tld',
134+
'x-managersname' => 'Manager',
135+
],
136+
$vCard->jsonSerialize()
137+
);
138+
}
139+
110140
protected function compareData($expected, $data) {
111141
foreach ($expected as $key => $value) {
112142
$found = false;
@@ -182,7 +212,7 @@ public function providesNewUsers() {
182212
* @param $fullName
183213
*/
184214
public function testNameSplitter($expected, $fullName): void {
185-
$converter = new Converter($this->accountManager);
215+
$converter = new Converter($this->accountManager, $this->userManager);
186216
$r = $converter->splitFullName($fullName);
187217
$r = implode(';', $r);
188218
$this->assertEquals($expected, $r);

apps/provisioning_api/lib/Controller/AUserData.php

+3
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ abstract class AUserData extends OCSController {
6060
public const USER_FIELD_LOCALE = 'locale';
6161
public const USER_FIELD_PASSWORD = 'password';
6262
public const USER_FIELD_QUOTA = 'quota';
63+
public const USER_FIELD_MANAGER = 'manager';
6364
public const USER_FIELD_NOTIFICATION_EMAIL = 'notify_email';
6465

6566
/** @var IUserManager */
@@ -151,6 +152,8 @@ protected function getUserData(string $userId, bool $includeScopes = false): arr
151152
$data['backend'] = $targetUserObject->getBackendClassName();
152153
$data['subadmin'] = $this->getUserSubAdminGroupsData($targetUserObject->getUID());
153154
$data[self::USER_FIELD_QUOTA] = $this->fillStorageInfo($targetUserObject->getUID());
155+
$managerUids = $targetUserObject->getManagerUids();
156+
$data[self::USER_FIELD_MANAGER] = empty($managerUids) ? '' : $managerUids[0];
154157

155158
try {
156159
if ($includeScopes) {

apps/provisioning_api/lib/Controller/UsersController.php

+18-2
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ public function addUser(
338338
array $groups = [],
339339
array $subadmin = [],
340340
string $quota = '',
341-
string $language = ''
341+
string $language = '',
342+
?string $manager = null,
342343
): DataResponse {
343344
$user = $this->userSession->getUser();
344345
$isAdmin = $this->groupManager->isAdmin($user->getUID());
@@ -447,6 +448,15 @@ public function addUser(
447448
$this->editUser($userid, self::USER_FIELD_LANGUAGE, $language);
448449
}
449450

451+
/**
452+
* null -> nothing sent
453+
* '' -> unset manager
454+
* else -> set manager
455+
*/
456+
if ($manager !== null) {
457+
$this->editUser($userid, self::USER_FIELD_MANAGER, $manager);
458+
}
459+
450460
// Send new user mail only if a mail is set
451461
if ($email !== '') {
452462
$newUser->setEMailAddress($email);
@@ -800,9 +810,11 @@ public function editUser(string $userId, string $key, string $value): DataRespon
800810

801811
$permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX;
802812

803-
// If admin they can edit their own quota
813+
// If admin they can edit their own quota and manager
804814
if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
805815
$permittedFields[] = self::USER_FIELD_QUOTA;
816+
$permittedFields[] = self::USER_FIELD_MANAGER;
817+
806818
}
807819
} else {
808820
// Check if admin / subadmin
@@ -836,6 +848,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
836848
$permittedFields[] = IAccountManager::PROPERTY_PROFILE_ENABLED;
837849
$permittedFields[] = self::USER_FIELD_QUOTA;
838850
$permittedFields[] = self::USER_FIELD_NOTIFICATION_EMAIL;
851+
$permittedFields[] = self::USER_FIELD_MANAGER;
839852
} else {
840853
// No rights
841854
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
@@ -885,6 +898,9 @@ public function editUser(string $userId, string $key, string $value): DataRespon
885898
}
886899
$targetUser->setQuota($quota);
887900
break;
901+
case self::USER_FIELD_MANAGER:
902+
$targetUser->setManagerUids([$value]);
903+
break;
888904
case self::USER_FIELD_PASSWORD:
889905
try {
890906
if (strlen($value) > IUserManager::MAX_PASSWORD_LENGTH) {

apps/provisioning_api/tests/Controller/UsersControllerTest.php

+3
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,7 @@ public function testGetUserDataAsAdmin() {
10931093
'biography' => 'biography',
10941094
'profile_enabled' => '1',
10951095
'notify_email' => null,
1096+
'manager' => '',
10961097
];
10971098
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
10981099
}
@@ -1233,6 +1234,7 @@ public function testGetUserDataAsSubAdminAndUserIsAccessible() {
12331234
'biography' => 'biography',
12341235
'profile_enabled' => '1',
12351236
'notify_email' => null,
1237+
'manager' => '',
12361238
];
12371239
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
12381240
}
@@ -1411,6 +1413,7 @@ public function testGetUserDataAsSubAdminSelfLookup() {
14111413
'biography' => 'biography',
14121414
'profile_enabled' => '1',
14131415
'notify_email' => null,
1416+
'manager' => '',
14141417
];
14151418
$this->assertEquals($expected, $this->invokePrivate($this->api, 'getUserData', ['UID']));
14161419
}

apps/settings/css/settings.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/settings/css/settings.css.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/settings/css/settings.scss

+3
Original file line numberDiff line numberDiff line change
@@ -1350,6 +1350,8 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
13501350
minmax($grid-col-min-width, 1fr) // email
13511351
minmax(1.5*$grid-col-min-width, 1fr) // groups
13521352
minmax(1.5*$grid-col-min-width, 1fr) // group admins
1353+
minmax($grid-col-min-width, 1fr) // quota
1354+
minmax(1.5*$grid-col-min-width, 1fr) // manager
13531355
repeat(auto-fit, minmax($grid-col-min-width, 1fr));
13541356
border-bottom: var(--color-border) 1px solid;
13551357

@@ -1394,6 +1396,7 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
13941396
}
13951397
}
13961398

1399+
.managers,
13971400
.groups,
13981401
.subadmins,
13991402
.quota {

0 commit comments

Comments
 (0)