BastionSSO/app/Console/Commands/UserManageCommand.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;
}
}