204 lines
6.8 KiB
PHP

<?php
namespace App\Http\Controllers\SystemSettings;
use App\Models\Auth\Role;
use App\Models\Auth\User;
use App\Models\Auth\UserAccessGroup;
use App\Utilities\AgreementSigningPermissions;
use App\Utilities\SystemAccess;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
class Users extends Controller
{
public function __construct()
{
$this->middleware(function ($request, $next) {
abort_unless(SystemAccess::canOpenSettings(), 403);
return $next($request);
});
}
public function index()
{
$users = $this->queryForActor()->with(['roles', 'dingtalkIdentity'])->orderBy('id')->get();
$groupNamesByUser = [];
foreach (UserAccessGroup::forCompany()->with('users')->get() as $group) {
foreach ($group->users as $member) {
$groupNamesByUser[$member->id][] = $group->name;
}
}
return view('system_settings.users.index', [
'users' => $users,
'roleLabels' => SystemAccess::roleLabels(),
'groupNamesByUser' => $groupNamesByUser,
]);
}
public function create()
{
return view('system_settings.users.form', [
'managedUser' => null,
'roles' => SystemAccess::assignableRoles(),
]);
}
public function store(Request $request)
{
$data = $this->validateUser($request);
$role = Role::where('name', $data['role'])->firstOrFail();
DB::transaction(function () use ($data, $role) {
$created = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => $data['password'],
'locale' => 'zh-CN',
'enabled' => (bool) ($data['enabled'] ?? false),
'landing_page' => 'dashboard',
'created_by' => user()->id,
'created_from' => 'system_settings',
]);
$created->roles()->attach($role->id);
$created->companies()->attach(company_id());
if (array_key_exists('agreement_signing_allowed', $data)) {
AgreementSigningPermissions::setGranted($created, (bool) $data['agreement_signing_allowed']);
}
});
flash('用户已新增。')->success();
return redirect()->route('system-settings.users.index');
}
public function edit(int $id)
{
$managedUser = $this->findManagedUser($id);
abort_unless(SystemAccess::canManageUser(user(), $managedUser), 403);
return view('system_settings.users.form', [
'managedUser' => $managedUser,
'roles' => SystemAccess::assignableRoles(),
]);
}
public function update(int $id, Request $request)
{
$managedUser = $this->findManagedUser($id);
abort_unless(SystemAccess::canManageUser(user(), $managedUser), 403);
$data = $this->validateUser($request, $managedUser);
$role = Role::where('name', $data['role'])->firstOrFail();
if (
SystemAccess::isSuperAdmin($managedUser)
&& $managedUser->enabled
&& ($data['role'] !== SystemAccess::SUPER_ADMIN || ! ($data['enabled'] ?? false))
&& $this->superAdminCount() <= 1
) {
return back()->withErrors([
$data['role'] !== SystemAccess::SUPER_ADMIN ? 'role' : 'enabled' => '系统至少需要保留一名启用的主管理员。',
])->withInput();
}
if ($managedUser->id === user()->id && ! ($data['enabled'] ?? false)) {
return back()->withErrors(['enabled' => '不能停用当前登录账号。'])->withInput();
}
DB::transaction(function () use ($managedUser, $data, $role) {
$attributes = [
'name' => $data['name'],
'email' => $data['email'],
'enabled' => (bool) ($data['enabled'] ?? false),
];
if (! empty($data['password'])) {
$attributes['password'] = $data['password'];
}
$managedUser->update($attributes);
$managedUser->syncRoles([$role->id]);
if (array_key_exists('agreement_signing_allowed', $data)) {
AgreementSigningPermissions::setGranted($managedUser, (bool) $data['agreement_signing_allowed']);
}
});
$managedUser->flushCache();
flash('用户已修改。')->success();
return redirect()->route('system-settings.users.index');
}
public function destroy(int $id)
{
$managedUser = $this->findManagedUser($id);
abort_if($managedUser->id === user()->id, 422, '不能删除当前登录账号。');
abort_unless(SystemAccess::canManageUser(user(), $managedUser), 403);
if (SystemAccess::isSuperAdmin($managedUser) && $managedUser->enabled && $this->superAdminCount() <= 1) {
return back()->withErrors(['user' => '系统至少需要保留一名启用的主管理员。']);
}
if ($managedUser->dingtalkIdentity()->exists()) {
return back()->withErrors(['user' => '钉钉绑定用户不能直接删除。需要停止访问时请停用账号,避免钉钉身份残留后无法再次登录。']);
}
$managedUser->delete();
flash('用户已删除。')->success();
return redirect()->route('system-settings.users.index');
}
private function queryForActor()
{
$query = User::query()->whereHas('companies', function ($company) {
$company->where('companies.id', company_id());
});
return $query;
}
private function findManagedUser(int $id): User
{
return $this->queryForActor()->with('roles')->findOrFail($id);
}
private function validateUser(Request $request, ?User $managedUser = null): array
{
$assignable = array_keys(SystemAccess::assignableRoles());
return $request->validate([
'name' => ['required', 'string', 'max:191'],
'email' => [
'required',
'email',
'max:191',
Rule::unique('users', 'email')->ignore($managedUser?->id)->whereNull('deleted_at'),
],
'role' => ['required', Rule::in($assignable)],
'password' => [$managedUser ? 'nullable' : 'required', 'string', 'min:8', 'confirmed'],
'enabled' => ['nullable', 'boolean'],
'agreement_signing_allowed' => ['sometimes', 'boolean'],
]);
}
private function superAdminCount(): int
{
return User::query()
->where('enabled', true)
->whereHas('roles', fn ($roles) => $roles->where('roles.name', SystemAccess::SUPER_ADMIN))
->count();
}
}