Files
2026-10-02 10:21:54 +01:00

157 lines
5.4 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Modules\Licensing\Models\License;
use Modules\Licensing\Models\LicenseActivation;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Password;
use Illuminate\Validation\Rule;
final class UserController extends Controller
{
public function index(Request $request)
{
$query = User::query()->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);
}
}