Skip to content

Commit 4902197

Browse files
authored
Merge pull request #59271 from nextcloud/feat/occ-group-add-user-batch
enh(occ): make it possible to add an arbitrary number of users to a g…
2 parents d6a7065 + 53cddbb commit 4902197

4 files changed

Lines changed: 213 additions & 31 deletions

File tree

core/Command/Group/AddUser.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ protected function configure() {
3535
'group to add the user to'
3636
)->addArgument(
3737
'user',
38-
InputArgument::REQUIRED,
39-
'user to add to the group'
38+
InputArgument::REQUIRED + InputArgument::IS_ARRAY,
39+
'users to add to the group',
4040
);
4141
}
4242

@@ -45,15 +45,35 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4545
$group = $this->groupManager->get($input->getArgument('group'));
4646
if (is_null($group)) {
4747
$output->writeln('<error>group not found</error>');
48-
return 1;
48+
return Base::FAILURE;
49+
}
50+
51+
$allUsersFound = true;
52+
$noUserFound = true;
53+
$users = (array)$input->getArgument('user');
54+
foreach ($users as $userId) {
55+
$user = $this->userManager->get($userId);
56+
if (is_null($user)) {
57+
$output->writeln('<error>user ' . $userId . ' not found</error>');
58+
$allUsersFound = false;
59+
continue;
60+
}
61+
$noUserFound = false;
62+
$group->addUser($user);
63+
unset($user);
64+
$output->writeln('<info>user ' . $userId . ' added</info>');
4965
}
50-
$user = $this->userManager->get($input->getArgument('user'));
51-
if (is_null($user)) {
52-
$output->writeln('<error>user not found</error>');
53-
return 1;
66+
67+
if (!$allUsersFound && !$noUserFound) {
68+
$output->writeln('<error>Some users were not found, all others where added to the group.</error>');
69+
return Base::FAILURE;
70+
}
71+
72+
if ($noUserFound) {
73+
return Base::FAILURE;
5474
}
55-
$group->addUser($user);
56-
return 0;
75+
76+
return Base::SUCCESS;
5777
}
5878

5979
/**

core/Command/Group/RemoveUser.php

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ protected function configure() {
3535
'group to remove the user from'
3636
)->addArgument(
3737
'user',
38-
InputArgument::REQUIRED,
39-
'user to remove from the group'
38+
InputArgument::REQUIRED + InputArgument::IS_ARRAY,
39+
'users to remove from the group'
4040
);
4141
}
4242

@@ -45,15 +45,35 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4545
$group = $this->groupManager->get($input->getArgument('group'));
4646
if (is_null($group)) {
4747
$output->writeln('<error>group not found</error>');
48-
return 1;
48+
return Base::FAILURE;
49+
}
50+
51+
$allUsersFound = true;
52+
$noUserFound = true;
53+
$users = (array)$input->getArgument('user');
54+
foreach ($users as $userId) {
55+
$user = $this->userManager->get($userId);
56+
if (is_null($user)) {
57+
$output->writeln('<error>user ' . $userId . ' not found</error>');
58+
$allUsersFound = false;
59+
continue;
60+
}
61+
$noUserFound = false;
62+
$group->removeUser($user);
63+
unset($user);
64+
$output->writeln('<info>user ' . $userId . ' removed</info>');
4965
}
50-
$user = $this->userManager->get($input->getArgument('user'));
51-
if (is_null($user)) {
52-
$output->writeln('<error>user not found</error>');
53-
return 1;
66+
67+
if (!$allUsersFound && !$noUserFound) {
68+
$output->writeln('<error>Some users were not found, all others where removed from the group.</error>');
69+
return Base::FAILURE;
70+
}
71+
72+
if ($noUserFound) {
73+
return Base::FAILURE;
5474
}
55-
$group->removeUser($user);
56-
return 0;
75+
76+
return Base::SUCCESS;
5777
}
5878

5979
/**

tests/Core/Command/Group/AddUserTest.php

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,26 @@ protected function setUp(): void {
3939
$this->groupManager = $this->createMock(IGroupManager::class);
4040
$this->userManager = $this->createMock(IUserManager::class);
4141
$this->command = new AddUser($this->userManager, $this->groupManager);
42+
$this->output = $this->createMock(OutputInterface::class);
43+
}
4244

45+
protected function configureInput(array|string $returnGroup, array|string $returnUser): void {
4346
$this->input = $this->createMock(InputInterface::class);
4447
$this->input->method('getArgument')
45-
->willReturnCallback(function ($arg) {
48+
->willReturnCallback(function ($arg) use ($returnGroup, $returnUser) {
4649
if ($arg === 'group') {
47-
return 'myGroup';
48-
} elseif ($arg === 'user') {
49-
return 'myUser';
50+
return $returnGroup;
51+
}
52+
if ($arg === 'user') {
53+
return $returnUser;
5054
}
5155
throw new \Exception();
5256
});
53-
$this->output = $this->createMock(OutputInterface::class);
5457
}
5558

5659
public function testNoGroup(): void {
60+
$this->configureInput('myGroup', 'myUser');
61+
5762
$this->groupManager->method('get')
5863
->with('myGroup')
5964
->willReturn(null);
@@ -66,6 +71,8 @@ public function testNoGroup(): void {
6671
}
6772

6873
public function testNoUser(): void {
74+
$this->configureInput('myGroup', 'myUser');
75+
6976
$group = $this->createMock(IGroup::class);
7077
$this->groupManager->method('get')
7178
->with('myGroup')
@@ -77,12 +84,14 @@ public function testNoUser(): void {
7784

7885
$this->output->expects($this->once())
7986
->method('writeln')
80-
->with('<error>user not found</error>');
87+
->with('<error>user myUser not found</error>');
8188

8289
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
8390
}
8491

8592
public function testAdd(): void {
93+
$this->configureInput('myGroup', 'myUser');
94+
8695
$group = $this->createMock(IGroup::class);
8796
$this->groupManager->method('get')
8897
->with('myGroup')
@@ -99,4 +108,66 @@ public function testAdd(): void {
99108

100109
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
101110
}
111+
112+
public function testAddMultiple(): void {
113+
$this->configureInput('myGroup', ['myUser', 'myOtherUser']);
114+
115+
$group = $this->createMock(IGroup::class);
116+
$this->groupManager->method('get')
117+
->with('myGroup')
118+
->willReturn($group);
119+
120+
$user1 = $this->createMock(IUser::class);
121+
$user2 = $this->createMock(IUser::class);
122+
$this->userManager->method('get')
123+
->willReturnMap([
124+
['myUser', $user1],
125+
['myOtherUser', $user2],
126+
]);
127+
128+
$group->expects($this->exactly(2))
129+
->method('addUser')
130+
->with($this->callback(static fn (IUser $user): bool => in_array($user, [$user1, $user2], true)));
131+
132+
$this->output->expects($this->exactly(2))
133+
->method('writeln')
134+
->with($this->callback(static fn (string $message): bool => in_array($message,
135+
[
136+
'<info>user myUser added</info>',
137+
'<info>user myOtherUser added</info>',
138+
], true)));
139+
140+
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
141+
}
142+
143+
public function testAddMultiplePartialSuccess(): void {
144+
$this->configureInput('myGroup', ['myUser', 'myOtherUser']);
145+
146+
$group = $this->createMock(IGroup::class);
147+
$this->groupManager->method('get')
148+
->with('myGroup')
149+
->willReturn($group);
150+
151+
$user = $this->createMock(IUser::class);
152+
$this->userManager->method('get')
153+
->willReturnMap([
154+
['myUser', $user],
155+
['myOtherUser', null],
156+
]);
157+
158+
$group->expects($this->once())
159+
->method('addUser')
160+
->with($user);
161+
162+
$this->output->expects($this->exactly(3))
163+
->method('writeln')
164+
->with($this->callback(static fn (string $message): bool => in_array($message,
165+
[
166+
'<info>user myUser added</info>',
167+
'<error>user myOtherUser not found</error>',
168+
'<error>Some users were not found, all others where added to the group.</error>',
169+
], true)));
170+
171+
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
172+
}
102173
}

tests/Core/Command/Group/RemoveUserTest.php

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,26 @@ protected function setUp(): void {
3939
$this->groupManager = $this->createMock(IGroupManager::class);
4040
$this->userManager = $this->createMock(IUserManager::class);
4141
$this->command = new RemoveUser($this->userManager, $this->groupManager);
42+
$this->output = $this->createMock(OutputInterface::class);
43+
}
4244

45+
protected function configureInput(array|string $returnGroup, array|string $returnUser): void {
4346
$this->input = $this->createMock(InputInterface::class);
4447
$this->input->method('getArgument')
45-
->willReturnCallback(function ($arg) {
48+
->willReturnCallback(function ($arg) use ($returnGroup, $returnUser) {
4649
if ($arg === 'group') {
47-
return 'myGroup';
48-
} elseif ($arg === 'user') {
49-
return 'myUser';
50+
return $returnGroup;
51+
}
52+
if ($arg === 'user') {
53+
return $returnUser;
5054
}
5155
throw new \Exception();
5256
});
53-
$this->output = $this->createMock(OutputInterface::class);
5457
}
5558

5659
public function testNoGroup(): void {
60+
$this->configureInput('myGroup', 'myUser');
61+
5762
$this->groupManager->method('get')
5863
->with('myGroup')
5964
->willReturn(null);
@@ -66,6 +71,8 @@ public function testNoGroup(): void {
6671
}
6772

6873
public function testNoUser(): void {
74+
$this->configureInput('myGroup', 'myUser');
75+
6976
$group = $this->createMock(IGroup::class);
7077
$this->groupManager->method('get')
7178
->with('myGroup')
@@ -77,12 +84,14 @@ public function testNoUser(): void {
7784

7885
$this->output->expects($this->once())
7986
->method('writeln')
80-
->with('<error>user not found</error>');
87+
->with('<error>user myUser not found</error>');
8188

8289
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
8390
}
8491

85-
public function testAdd(): void {
92+
public function testRemove(): void {
93+
$this->configureInput('myGroup', 'myUser');
94+
8695
$group = $this->createMock(IGroup::class);
8796
$this->groupManager->method('get')
8897
->with('myGroup')
@@ -99,4 +108,66 @@ public function testAdd(): void {
99108

100109
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
101110
}
111+
112+
public function testRemoveMultiple(): void {
113+
$this->configureInput('myGroup', ['myUser', 'myOtherUser']);
114+
115+
$group = $this->createMock(IGroup::class);
116+
$this->groupManager->method('get')
117+
->with('myGroup')
118+
->willReturn($group);
119+
120+
$user1 = $this->createMock(IUser::class);
121+
$user2 = $this->createMock(IUser::class);
122+
$this->userManager->method('get')
123+
->willReturnMap([
124+
['myUser', $user1],
125+
['myOtherUser', $user2],
126+
]);
127+
128+
$group->expects($this->exactly(2))
129+
->method('removeUser')
130+
->with($this->callback(static fn (IUser $user): bool => in_array($user, [$user1, $user2], true)));
131+
132+
$this->output->expects($this->exactly(2))
133+
->method('writeln')
134+
->with($this->callback(static fn (string $message): bool => in_array($message,
135+
[
136+
'<info>user myUser removed</info>',
137+
'<info>user myOtherUser removed</info>',
138+
], true)));
139+
140+
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
141+
}
142+
143+
public function testRemoveMultiplePartialSuccess(): void {
144+
$this->configureInput('myGroup', ['myUser', 'myOtherUser']);
145+
146+
$group = $this->createMock(IGroup::class);
147+
$this->groupManager->method('get')
148+
->with('myGroup')
149+
->willReturn($group);
150+
151+
$user = $this->createMock(IUser::class);
152+
$this->userManager->method('get')
153+
->willReturnMap([
154+
['myUser', $user],
155+
['myOtherUser', null],
156+
]);
157+
158+
$group->expects($this->once())
159+
->method('removeUser')
160+
->with($user);
161+
162+
$this->output->expects($this->exactly(3))
163+
->method('writeln')
164+
->with($this->callback(static fn (string $message): bool => in_array($message,
165+
[
166+
'<info>user myUser removed</info>',
167+
'<error>user myOtherUser not found</error>',
168+
'<error>Some users were not found, all others where removed from the group.</error>',
169+
], true)));
170+
171+
$this->invokePrivate($this->command, 'execute', [$this->input, $this->output]);
172+
}
102173
}

0 commit comments

Comments
 (0)