373 lines
9.6 KiB
PHP
373 lines
9.6 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\User;
|
|
use App\Models\UserServerPermission;
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Spatie\Permission\Models\Permission;
|
|
use Spatie\Permission\Models\Role;
|
|
|
|
class UserManageCommand extends Command
|
|
{
|
|
protected $signature = 'user:manage
|
|
{action : create|reset-password|list|init-rbac|create-role|assign-role|remove-role|assign-permission|remove-permission|grant-server|set-admin|unset-admin}
|
|
{--email= : User email}
|
|
{--nickname= : User nickname}
|
|
{--phone= : User phone}
|
|
{--password= : User password}
|
|
{--role= : Role name}
|
|
{--permission= : Permission name}
|
|
{--server-id= : Server resource id}
|
|
{--ssh=0 : Grant ssh 1|0}
|
|
{--sftp=0 : Grant sftp 1|0}
|
|
{--rdp=0 : Grant rdp 1|0}';
|
|
|
|
protected $description = 'User and permission management command';
|
|
|
|
public function handle(): int
|
|
{
|
|
return match ($this->argument('action')) {
|
|
'create' => $this->createUser(),
|
|
'reset-password' => $this->resetPassword(),
|
|
'list' => $this->listUsers(),
|
|
'init-rbac' => $this->initRbac(),
|
|
'create-role' => $this->createRole(),
|
|
'assign-role' => $this->assignRole(),
|
|
'remove-role' => $this->removeRole(),
|
|
'assign-permission' => $this->assignPermission(),
|
|
'remove-permission' => $this->removePermission(),
|
|
'grant-server' => $this->grantServerPermission(),
|
|
'set-admin' => $this->setAdmin(),
|
|
'unset-admin' => $this->unsetAdmin(),
|
|
default => $this->invalidAction(),
|
|
};
|
|
}
|
|
|
|
private function createUser(): int
|
|
{
|
|
$email = (string) $this->option('email');
|
|
$nickname = (string) $this->option('nickname');
|
|
$password = (string) $this->option('password');
|
|
|
|
if ($email === '' || $nickname === '' || $password === '') {
|
|
$this->error('email, nickname, password are required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user = User::query()->create([
|
|
'email' => $email,
|
|
'nickname' => $nickname,
|
|
'phone' => $this->option('phone') ?: null,
|
|
'password' => $password,
|
|
]);
|
|
|
|
if ($this->option('role')) {
|
|
$role = Role::query()->firstOrCreate([
|
|
'name' => (string) $this->option('role'),
|
|
'guard_name' => 'api',
|
|
]);
|
|
$user->assignRole($role);
|
|
}
|
|
|
|
$this->info("User created: {$user->id}");
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function resetPassword(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$password = (string) $this->option('password');
|
|
|
|
if ($password === '') {
|
|
$this->error('password is required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user->password = Hash::make($password);
|
|
$user->save();
|
|
|
|
$this->info('Password reset success.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function listUsers(): int
|
|
{
|
|
$rows = User::query()->with(['roles', 'permissions'])->latest()->get()->map(fn (User $user): array => [
|
|
'id' => $user->id,
|
|
'nickname' => $user->nickname,
|
|
'email' => $user->email,
|
|
'roles' => $user->roles->pluck('name')->implode(','),
|
|
'permissions' => $user->permissions->pluck('name')->implode(','),
|
|
])->toArray();
|
|
|
|
$this->table(['ID', 'Nickname', 'Email', 'Roles', 'Permissions'], $rows);
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function initRbac(): int
|
|
{
|
|
$permissions = [
|
|
'platform.users.view',
|
|
'platform.users.manage',
|
|
'platform.roles.view',
|
|
'platform.roles.manage',
|
|
'platform.permissions.view',
|
|
'platform.permissions.manage',
|
|
'platform.servers.view',
|
|
'platform.servers.manage',
|
|
'platform.accounts.view',
|
|
'platform.accounts.manage',
|
|
'platform.logs.view',
|
|
'platform.logs.manage',
|
|
'resource.servers.use',
|
|
];
|
|
|
|
foreach ($permissions as $permissionName) {
|
|
Permission::query()->firstOrCreate([
|
|
'name' => $permissionName,
|
|
'guard_name' => 'api',
|
|
]);
|
|
}
|
|
|
|
$adminRole = Role::query()->firstOrCreate([
|
|
'name' => 'admin',
|
|
'guard_name' => 'api',
|
|
]);
|
|
|
|
$userRole = Role::query()->firstOrCreate([
|
|
'name' => 'user',
|
|
'guard_name' => 'api',
|
|
]);
|
|
|
|
$adminRole->syncPermissions($permissions);
|
|
$userRole->syncPermissions([
|
|
'resource.servers.use',
|
|
]);
|
|
|
|
Role::query()->where('guard_name', 'api')->whereIn('name', ['operator', 'member'])->delete();
|
|
|
|
$this->info('RBAC initialized.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function createRole(): int
|
|
{
|
|
$roleName = (string) $this->option('role');
|
|
|
|
if ($roleName === '') {
|
|
$this->error('role is required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
Role::query()->firstOrCreate([
|
|
'name' => $roleName,
|
|
'guard_name' => 'api',
|
|
]);
|
|
|
|
$this->info('Role created.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function assignRole(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$roleName = (string) $this->option('role');
|
|
|
|
if ($roleName === '') {
|
|
$this->error('role is required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user->assignRole($roleName);
|
|
$this->info('Role assigned.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function removeRole(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$roleName = (string) $this->option('role');
|
|
|
|
if ($roleName === '') {
|
|
$this->error('role is required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user->removeRole($roleName);
|
|
$this->info('Role removed.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function assignPermission(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$permission = (string) $this->option('permission');
|
|
|
|
if ($permission === '') {
|
|
$this->error('permission is required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user->givePermissionTo($permission);
|
|
$this->info('Permission assigned.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function removePermission(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$permission = (string) $this->option('permission');
|
|
|
|
if ($permission === '') {
|
|
$this->error('permission is required.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$user->revokePermissionTo($permission);
|
|
$this->info('Permission removed.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function grantServerPermission(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$serverId = (int) $this->option('server-id');
|
|
|
|
if ($serverId <= 0) {
|
|
$this->error('server-id is required and must be > 0.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
|
|
UserServerPermission::query()->updateOrCreate(
|
|
['user_id' => $user->id, 'server_resource_id' => $serverId],
|
|
[
|
|
'can_ssh' => (bool) ((int) $this->option('ssh')),
|
|
'can_sftp' => (bool) ((int) $this->option('sftp')),
|
|
'can_rdp' => (bool) ((int) $this->option('rdp')),
|
|
]
|
|
);
|
|
|
|
$this->info('Server permission updated.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function setAdmin(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
$adminRole = Role::query()->firstOrCreate([
|
|
'name' => 'admin',
|
|
'guard_name' => 'api',
|
|
]);
|
|
|
|
$allPermissions = Permission::query()
|
|
->where('guard_name', 'api')
|
|
->pluck('name')
|
|
->all();
|
|
|
|
$adminRole->syncPermissions($allPermissions);
|
|
|
|
$user->syncRoles([$adminRole->name]);
|
|
$user->syncPermissions([]);
|
|
|
|
$this->info('User set as admin with all permissions.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function unsetAdmin(): int
|
|
{
|
|
$user = $this->findUserByEmail();
|
|
if (! $user) {
|
|
return self::FAILURE;
|
|
}
|
|
|
|
if (! $user->hasRole('admin', 'api')) {
|
|
$this->warn('User is not admin.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$user->removeRole('admin');
|
|
|
|
$this->info('Admin role removed from user.');
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function findUserByEmail(): ?User
|
|
{
|
|
$email = (string) $this->option('email');
|
|
|
|
if ($email === '') {
|
|
$this->error('email is required.');
|
|
|
|
return null;
|
|
}
|
|
|
|
$user = User::query()->where('email', $email)->first();
|
|
|
|
if (! $user) {
|
|
$this->error('User not found.');
|
|
|
|
return null;
|
|
}
|
|
|
|
return $user;
|
|
}
|
|
|
|
private function invalidAction(): int
|
|
{
|
|
$this->error('Invalid action.');
|
|
|
|
return self::FAILURE;
|
|
}
|
|
}
|