229 lines
8.5 KiB
PHP
229 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\User;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\View\View;
|
|
|
|
class UserController extends Controller
|
|
{
|
|
public function index(Request $request)
|
|
{
|
|
$q = trim((string) $request->query('q', ''));
|
|
|
|
$users = User::query()
|
|
->when($q, fn ($query) => $query->where(function ($sub) use ($q) {
|
|
$sub->where('name', 'like', "%{$q}%")->orWhere('email', 'like', "%{$q}%");
|
|
}))
|
|
->orderByDesc('created_at')
|
|
->paginate(20)
|
|
->withQueryString();
|
|
|
|
return view('admin.users.index', compact('users', 'q'));
|
|
}
|
|
|
|
/**
|
|
* 新建用户表单(角色 + 权限分配)。
|
|
*/
|
|
public function create(): View
|
|
{
|
|
$roles = config('permissions.roles');
|
|
$groups = config('permissions.groups');
|
|
$permissions = config('permissions.permissions');
|
|
|
|
return view('admin.users.create', compact('roles', 'groups', 'permissions'));
|
|
}
|
|
|
|
/**
|
|
* 新建用户,受层级约束:不能创建权限高于或等于自身角色的用户。
|
|
*/
|
|
public function store(Request $request): RedirectResponse
|
|
{
|
|
$current = $request->user();
|
|
|
|
$allPermKeys = implode(',', array_keys(config('permissions.permissions')));
|
|
$data = $request->validate([
|
|
'name' => ['required', 'string', 'max:60'],
|
|
'email' => ['required', 'email', 'unique:users,email'],
|
|
'password' => ['required', 'string', 'min:8'],
|
|
'role' => ['required', 'in:super_admin,admin,forum_admin,staff,user'],
|
|
'permissions' => ['nullable', 'array'],
|
|
'permissions.*' => ['string', "in:{$allPermKeys}"],
|
|
]);
|
|
|
|
// 层级防护:不能创建高于或等于自身权限的角色
|
|
if (! $current->isSuperAdmin() && $current->roleLevel() <= $this->roleLevelOf($data['role'])) {
|
|
return back()->withErrors(['role' => '您只能创建权限低于自身的用户'])->withInput();
|
|
}
|
|
if ($data['role'] === 'super_admin' && ! $current->isSuperAdmin()) {
|
|
return back()->withErrors(['role' => '只有超级管理员可以创建超级管理员'])->withInput();
|
|
}
|
|
|
|
$permissions = $data['role'] === 'staff'
|
|
? array_values(array_unique($data['permissions'] ?? []))
|
|
: null;
|
|
|
|
$user = User::create([
|
|
'name' => $data['name'],
|
|
'email' => $data['email'],
|
|
'password' => Hash::make($data['password']),
|
|
'role' => $data['role'],
|
|
'is_admin' => $data['role'] !== 'user',
|
|
'permissions' => $permissions,
|
|
'points' => 0,
|
|
]);
|
|
|
|
return redirect()->route('admin.users.index')
|
|
->with('success', "已创建用户 {$user->name}");
|
|
}
|
|
|
|
/**
|
|
* 编辑用户角色与权限(内部员工可勾选细粒度权限)。
|
|
*/
|
|
public function edit(User $user)
|
|
{
|
|
$roles = config('permissions.roles');
|
|
$groups = config('permissions.groups');
|
|
$permissions = config('permissions.permissions');
|
|
$userPerms = is_array($user->permissions) ? $user->permissions : [];
|
|
|
|
$canManage = $this->canManage($user);
|
|
|
|
return view('admin.users.edit', compact('user', 'roles', 'groups', 'permissions', 'userPerms', 'canManage'));
|
|
}
|
|
|
|
/**
|
|
* 更新用户角色与权限,受层级约束。
|
|
*/
|
|
public function update(Request $request, User $user): RedirectResponse
|
|
{
|
|
$current = $request->user();
|
|
|
|
// 防锁死:禁止改动自己
|
|
if ($user->id === $current->id) {
|
|
return back()->withErrors(['role' => '不能修改当前登录账号的角色/权限']);
|
|
}
|
|
|
|
// 层级防护:非超管不能触碰同级或更高权限用户
|
|
if (! $current->isSuperAdmin() && $current->roleLevel() <= $user->roleLevel()) {
|
|
return back()->withErrors(['role' => '您只能修改权限低于自身的用户']);
|
|
}
|
|
if ($user->isSuperAdmin() && ! $current->isSuperAdmin()) {
|
|
return back()->withErrors(['role' => '只有超级管理员可以调整超级管理员']);
|
|
}
|
|
|
|
$allPermKeys = implode(',', array_keys(config('permissions.permissions')));
|
|
$data = $request->validate([
|
|
'role' => ['required', 'in:super_admin,admin,forum_admin,staff,user'],
|
|
'permissions' => ['nullable', 'array'],
|
|
'permissions.*' => ['string', "in:{$allPermKeys}"],
|
|
]);
|
|
|
|
// 越权防护:不能分配高于或等于自身权限的角色
|
|
if ($data['role'] === 'super_admin' && ! $current->isSuperAdmin()) {
|
|
return back()->withErrors(['role' => '只有超级管理员可以分配超级管理员角色']);
|
|
}
|
|
if (! $current->isSuperAdmin() && $current->roleLevel() <= $this->roleLevelOf($data['role'])) {
|
|
return back()->withErrors(['role' => '您只能分配权限低于自身的角色']);
|
|
}
|
|
|
|
$permissions = $data['role'] === 'staff'
|
|
? array_values(array_unique($data['permissions'] ?? []))
|
|
: null;
|
|
|
|
$user->update([
|
|
'role' => $data['role'],
|
|
'is_admin' => $data['role'] !== 'user',
|
|
'permissions' => $permissions,
|
|
]);
|
|
|
|
return redirect()->route('admin.users.index')
|
|
->with('success', "已更新 {$user->name} 的角色与权限");
|
|
}
|
|
|
|
/**
|
|
* 重置指定用户密码(管理员代操作):可指定新密码,留空则生成随机密码并回显。
|
|
* 受层级约束,且禁止重置当前登录账号(请用「修改密码」)。
|
|
*/
|
|
public function resetPassword(Request $request, User $user): RedirectResponse
|
|
{
|
|
$current = $request->user();
|
|
|
|
if ($user->id === $current->id) {
|
|
return back()->withErrors(['password' => '不能重置当前登录账号的密码,请到「修改密码」操作']);
|
|
}
|
|
if (! $current->isSuperAdmin() && $current->roleLevel() <= $user->roleLevel()) {
|
|
return back()->withErrors(['password' => '您只能重置权限低于自身的用户密码']);
|
|
}
|
|
if ($user->isSuperAdmin() && ! $current->isSuperAdmin()) {
|
|
return back()->withErrors(['password' => '只有超级管理员可以重置超级管理员密码']);
|
|
}
|
|
|
|
$data = $request->validate([
|
|
'password' => ['nullable', 'string', 'min:8', 'confirmed'],
|
|
]);
|
|
|
|
if (! empty($data['password'])) {
|
|
$new = $data['password'];
|
|
$msg = '密码已重置';
|
|
} else {
|
|
$new = $this->generatePassword(12);
|
|
$msg = '密码已重置为随机密码:' . $new . '(请妥善告知用户,并建议其尽快修改)';
|
|
}
|
|
|
|
$user->update(['password' => Hash::make($new)]);
|
|
|
|
return redirect()->route('admin.users.edit', $user)->with('success', $msg);
|
|
}
|
|
|
|
public function destroy(User $user): RedirectResponse
|
|
{
|
|
$current = request()->user();
|
|
|
|
if ($user->id === $current->id) {
|
|
return back()->withErrors(['name' => '不能删除当前登录账号']);
|
|
}
|
|
if (! $current->isSuperAdmin() && $current->roleLevel() <= $user->roleLevel()) {
|
|
return back()->withErrors(['name' => '您只能删除权限低于自身的用户']);
|
|
}
|
|
if ($user->isSuperAdmin() && ! $current->isSuperAdmin()) {
|
|
return back()->withErrors(['name' => '只有超级管理员可以删除超级管理员']);
|
|
}
|
|
|
|
$user->delete();
|
|
|
|
return redirect()->route('admin.users.index')->with('success', '用户已删除');
|
|
}
|
|
|
|
/**
|
|
* 当前用户是否可管理目标用户(用于视图显隐操作按钮)。
|
|
*/
|
|
protected function canManage(User $user): bool
|
|
{
|
|
$current = request()->user();
|
|
if ($current->isSuperAdmin()) {
|
|
return true;
|
|
}
|
|
return $current->roleLevel() > $user->roleLevel();
|
|
}
|
|
|
|
protected function roleLevelOf(string $role): int
|
|
{
|
|
return (int) config("permissions.roles.{$role}.level", 1);
|
|
}
|
|
|
|
protected function generatePassword(int $len): string
|
|
{
|
|
$pool = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
|
$out = '';
|
|
for ($i = 0; $i < $len; $i++) {
|
|
$out .= $pool[random_int(0, strlen($pool) - 1)];
|
|
}
|
|
return $out;
|
|
}
|
|
}
|