latest(); if ($search = trim((string) $request->query('q'))) { $query->where(fn ($q) => $q ->where('name', 'like', "%{$search}%") ->orWhere('email', 'like', "%{$search}%")); } if ($request->query('status') === 'admin') { $query->where('is_admin', true); } elseif ($request->query('status') === 'suspended') { $query->whereNotNull('disabled_at'); } elseif ($request->query('status') === 'unverified') { $query->whereNull('email_verified_at'); } $users = $query->paginate(50)->withQueryString(); $emails = $users->getCollection()->pluck('email')->map(fn ($email) => strtolower($email))->all(); $licenseCounts = License::query() ->selectRaw('LOWER(customer_email) as email_key, COUNT(*) as aggregate') ->whereIn(DB::raw('LOWER(customer_email)'), $emails) ->groupBy(DB::raw('LOWER(customer_email)')) ->pluck('aggregate', 'email_key'); return view('admin.users.index', compact('users', 'licenseCounts')); } public function show(User $user) { $licenses = License::with(['product', 'activations']) ->whereRaw('LOWER(customer_email) = ?', [strtolower($user->email)]) ->latest() ->get(); return view('admin.users.show', compact('user', 'licenses')); } public function update(Request $request, User $user) { $data = $request->validate([ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'email', 'max:255', Rule::unique('users', 'email')->ignore($user->id)], 'is_admin' => ['nullable', 'boolean'], ]); $oldEmail = strtolower($user->email); $newEmail = strtolower(trim($data['email'])); $isSelf = $request->user()->is($user); DB::transaction(function () use ($user, $data, $oldEmail, $newEmail, $isSelf): void { $user->name = trim($data['name']); $user->email = $newEmail; if (! $isSelf) { $user->is_admin = (bool) ($data['is_admin'] ?? false); } $user->save(); if ($oldEmail !== $newEmail) { License::whereRaw('LOWER(customer_email) = ?', [$oldEmail]) ->update(['customer_email' => $newEmail]); } }); return redirect()->route('admin.users.show', $user)->with('status', 'User updated.'); } public function verify(User $user) { if (! $user->hasVerifiedEmail()) { $user->markEmailAsVerified(); } return back()->with('status', 'Email marked as verified.'); } public function resendVerification(User $user) { if (! $user->hasVerifiedEmail()) { $user->sendEmailVerificationNotification(); } return back()->with('status', 'Verification email sent.'); } public function sendPasswordReset(User $user) { $status = Password::sendResetLink(['email' => $user->email]); return $status === Password::RESET_LINK_SENT ? back()->with('status', 'Password reset link sent.') : back()->withErrors(['email' => __($status)]); } public function suspend(Request $request, User $user) { abort_if($request->user()->is($user), 422, 'You cannot suspend your own administrator account.'); $user->forceFill(['disabled_at' => now(), 'remember_token' => null])->save(); return back()->with('status', 'User suspended.'); } public function restore(User $user) { $user->forceFill(['disabled_at' => null])->save(); return back()->with('status', 'User restored.'); } public function destroy(Request $request, User $user) { abort_if($request->user()->is($user), 422, 'You cannot delete your own administrator account.'); $user->delete(); return redirect()->route('admin.users.index')->with('status', 'User deleted. Licences were retained.'); } public function updateLicense(Request $request, User $user, License $license) { $this->ensureOwnsLicense($user, $license); $data = $request->validate(['activation_limit' => ['required', 'integer', 'min:1', 'max:1000']]); $license->update(['activation_limit' => $data['activation_limit']]); return back()->with('status', 'Activation limit updated.'); } public function deactivate(User $user, License $license, LicenseActivation $activation) { $this->ensureOwnsLicense($user, $license); abort_unless((string) $activation->license_id === (string) $license->id, 404); $activation->update(['deactivated_at' => now()]); return back()->with('status', 'Device activation released.'); } private function ensureOwnsLicense(User $user, License $license): void { abort_unless(strtolower((string) $license->customer_email) === strtolower($user->email), 404); } }