Skip to content

Commit 60f1ae3

Browse files
authored
Merge pull request #1164 from kenjis/feat-command-user-create-g-option
feat: add -g option to `shield:user create`
2 parents 2554481 + 2e7c54b commit 60f1ae3

File tree

6 files changed

+116
-22
lines changed

6 files changed

+116
-22
lines changed

phpstan-baseline.php

+13-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@
159159
'count' => 1,
160160
'path' => __DIR__ . '/src/Collectors/Auth.php',
161161
];
162+
$ignoreErrors[] = [
163+
// identifier: codeigniter.factoriesClassConstFetch
164+
'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\GroupModel\\:\\:class is discouraged\\.$#',
165+
'count' => 1,
166+
'path' => __DIR__ . '/src/Commands/User.php',
167+
];
162168
$ignoreErrors[] = [
163169
// identifier: codeigniter.factoriesClassConstFetch
164170
'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserModel\\:\\:class is discouraged\\.$#',
@@ -259,7 +265,7 @@
259265
$ignoreErrors[] = [
260266
// identifier: codeigniter.factoriesClassConstFetch
261267
'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\GroupModel\\:\\:class is discouraged\\.$#',
262-
'count' => 2,
268+
'count' => 4,
263269
'path' => __DIR__ . '/src/Entities/User.php',
264270
];
265271
$ignoreErrors[] = [
@@ -330,6 +336,12 @@
330336
'count' => 1,
331337
'path' => __DIR__ . '/src/Models/UserIdentityModel.php',
332338
];
339+
$ignoreErrors[] = [
340+
// identifier: codeigniter.factoriesClassConstFetch
341+
'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\GroupModel\\:\\:class is discouraged\\.$#',
342+
'count' => 1,
343+
'path' => __DIR__ . '/src/Models/UserModel.php',
344+
];
333345
$ignoreErrors[] = [
334346
// identifier: codeigniter.factoriesClassConstFetch
335347
'message' => '#^Call to function model with CodeIgniter\\\\Shield\\\\Models\\\\UserIdentityModel\\:\\:class is discouraged\\.$#',

src/Authorization/Traits/Authorizable.php

+7-13
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ public function addGroup(string ...$groups): self
3333
{
3434
$this->populateGroups();
3535

36-
$configGroups = $this->getConfigGroups();
37-
3836
$groupCount = count($this->groupCache);
3937

4038
foreach ($groups as $group) {
@@ -45,8 +43,11 @@ public function addGroup(string ...$groups): self
4543
continue;
4644
}
4745

46+
/** @var GroupModel $groupModel */
47+
$groupModel = model(GroupModel::class);
48+
4849
// make sure it's a valid group
49-
if (! in_array($group, $configGroups, true)) {
50+
if (! $groupModel->isValidGroup($group)) {
5051
throw AuthorizationException::forUnknownGroup($group);
5152
}
5253

@@ -96,10 +97,11 @@ public function syncGroups(string ...$groups): self
9697
{
9798
$this->populateGroups();
9899

99-
$configGroups = $this->getConfigGroups();
100+
/** @var GroupModel $groupModel */
101+
$groupModel = model(GroupModel::class);
100102

101103
foreach ($groups as $group) {
102-
if (! in_array($group, $configGroups, true)) {
104+
if (! $groupModel->isValidGroup($group)) {
103105
throw AuthorizationException::forUnknownGroup($group);
104106
}
105107
}
@@ -398,14 +400,6 @@ private function saveGroupsOrPermissions(string $type, $model, array $cache): vo
398400
}
399401
}
400402

401-
/**
402-
* @return list<string>
403-
*/
404-
private function getConfigGroups(): array
405-
{
406-
return array_keys(setting('AuthGroups.groups'));
407-
}
408-
409403
/**
410404
* @return list<string>
411405
*/

src/Commands/User.php

+28-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use CodeIgniter\Shield\Config\Auth;
2020
use CodeIgniter\Shield\Entities\User as UserEntity;
2121
use CodeIgniter\Shield\Exceptions\UserNotFoundException;
22+
use CodeIgniter\Shield\Models\GroupModel;
2223
use CodeIgniter\Shield\Models\UserModel;
2324
use CodeIgniter\Shield\Validation\ValidationRules;
2425
use Config\Services;
@@ -53,6 +54,7 @@ class User extends BaseCommand
5354
shield:user <action> options
5455
5556
shield:user create -n newusername -e [email protected]
57+
shield:user create -n newusername -e [email protected] -g mygroup
5658
5759
shield:user activate -n username
5860
shield:user activate -e [email protected]
@@ -159,7 +161,7 @@ public function run(array $params): int
159161
try {
160162
switch ($action) {
161163
case 'create':
162-
$this->create($username, $email);
164+
$this->create($username, $email, $group);
163165
break;
164166

165167
case 'activate':
@@ -252,8 +254,9 @@ private function setValidationRules(): void
252254
*
253255
* @param string|null $username User name to create (optional)
254256
* @param string|null $email User email to create (optional)
257+
* @param string|null $group Group to add user to (optional)
255258
*/
256-
private function create(?string $username = null, ?string $email = null): void
259+
private function create(?string $username = null, ?string $email = null, ?string $group = null): void
257260
{
258261
$data = [];
259262

@@ -303,6 +306,11 @@ private function create(?string $username = null, ?string $email = null): void
303306

304307
$user = new UserEntity($data);
305308

309+
// Validate the group
310+
if ($group !== null && ! $this->validateGroup($group)) {
311+
throw new CancelException('Invalid group: "' . $group . '"');
312+
}
313+
306314
if ($username === null) {
307315
$userModel->allowEmptyInserts()->save($user);
308316
$this->write('New User created', 'green');
@@ -311,11 +319,26 @@ private function create(?string $username = null, ?string $email = null): void
311319
$this->write('User "' . $username . '" created', 'green');
312320
}
313321

314-
// Add to default group
315322
$user = $userModel->findById($userModel->getInsertID());
316-
$userModel->addToDefaultGroup($user);
317323

318-
$this->write('The user is added to the default group.', 'green');
324+
if ($group === null) {
325+
// Add to default group
326+
$userModel->addToDefaultGroup($user);
327+
328+
$this->write('The user is added to the default group.', 'green');
329+
} else {
330+
$user->addGroup($group);
331+
332+
$this->write('The user is added to group "' . $group . '".', 'green');
333+
}
334+
}
335+
336+
private function validateGroup(string $group): bool
337+
{
338+
/** @var GroupModel $groupModel */
339+
$groupModel = model(GroupModel::class);
340+
341+
return $groupModel->isValidGroup($group);
319342
}
320343

321344
/**

src/Models/GroupModel.php

+10
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,14 @@ public function deleteNotIn($userId, $cache): void
7373

7474
$this->checkQueryReturn($return);
7575
}
76+
77+
/**
78+
* @param non-empty-string $group Group name
79+
*/
80+
public function isValidGroup(string $group): bool
81+
{
82+
$allowedGroups = array_keys(setting('AuthGroups.groups'));
83+
84+
return in_array($group, $allowedGroups, true);
85+
}
7686
}

src/Models/UserModel.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,12 @@ private function assignIdentities(array $data, array $identities): array
153153
*/
154154
public function addToDefaultGroup(User $user): void
155155
{
156-
$defaultGroup = setting('AuthGroups.defaultGroup');
157-
$allowedGroups = array_keys(setting('AuthGroups.groups'));
156+
$defaultGroup = setting('AuthGroups.defaultGroup');
158157

159-
if (empty($defaultGroup) || ! in_array($defaultGroup, $allowedGroups, true)) {
158+
/** @var GroupModel $groupModel */
159+
$groupModel = model(GroupModel::class);
160+
161+
if (empty($defaultGroup) || ! $groupModel->isValidGroup($defaultGroup)) {
160162
throw new InvalidArgumentException(lang('Auth.unknownGroup', [$defaultGroup ?? '--not found--']));
161163
}
162164

tests/Commands/UserTest.php

+53
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,59 @@ public function testCreate(): void
100100
]);
101101
}
102102

103+
public function testCreateWithGroupBeta(): void
104+
{
105+
$this->setMockIo([
106+
'Secret Passw0rd!',
107+
'Secret Passw0rd!',
108+
]);
109+
110+
command('shield:user create -n user1 -e [email protected] -g beta');
111+
112+
$this->assertStringContainsString(
113+
'User "user1" created',
114+
$this->io->getFirstOutput()
115+
);
116+
$this->assertStringContainsString(
117+
'The user is added to group "beta"',
118+
$this->io->getFirstOutput()
119+
);
120+
121+
$users = model(UserModel::class);
122+
$user = $users->findByCredentials(['email' => '[email protected]']);
123+
$this->seeInDatabase($this->tables['identities'], [
124+
'user_id' => $user->id,
125+
'secret' => '[email protected]',
126+
]);
127+
$this->seeInDatabase($this->tables['users'], [
128+
'id' => $user->id,
129+
'active' => 0,
130+
]);
131+
$this->seeInDatabase($this->tables['groups_users'], [
132+
'user_id' => $user->id,
133+
'group' => 'beta',
134+
]);
135+
}
136+
137+
public function testCreateWithInvalidGroup(): void
138+
{
139+
$this->setMockIo([
140+
'Secret Passw0rd!',
141+
'Secret Passw0rd!',
142+
]);
143+
144+
command('shield:user create -n user1 -e [email protected] -g invalid');
145+
146+
$this->assertStringContainsString(
147+
'Invalid group: "invalid"',
148+
$this->io->getFirstOutput()
149+
);
150+
151+
$users = model(UserModel::class);
152+
$user = $users->findByCredentials(['email' => '[email protected]']);
153+
$this->assertNull($user);
154+
}
155+
103156
public function testCreateNotUniqueName(): void
104157
{
105158
$user = $this->createUser([

0 commit comments

Comments
 (0)