初始化

This commit is contained in:
2026-08-08 18:27:38 +08:00
parent efc150c937
commit 060eb79c09
336 changed files with 24613 additions and 15 deletions
@@ -0,0 +1,228 @@
<?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;
}
}