Files
SkinbaseNova/app/Http/Controllers/Api/Admin/UsernameApprovalController.php

150 lines
4.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\Admin;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Support\UsernamePolicy;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Symfony\Component\HttpFoundation\Response;
final class UsernameApprovalController extends Controller
{
public function pending(): JsonResponse
{
$rows = DB::table('username_approval_requests')
->where('status', 'pending')
->orderBy('created_at')
->get([
'id',
'user_id',
'requested_username',
'context',
'similar_to',
'payload',
'created_at',
]);
return response()->json(['data' => $rows], Response::HTTP_OK);
}
public function approve(int $id, Request $request): JsonResponse
{
$row = DB::table('username_approval_requests')->where('id', $id)->first();
if (! $row) {
return response()->json(['message' => 'Request not found.'], Response::HTTP_NOT_FOUND);
}
if ((string) $row->status !== 'pending') {
return response()->json(['message' => 'Request is not pending.'], Response::HTTP_UNPROCESSABLE_ENTITY);
}
DB::beginTransaction();
try {
DB::table('username_approval_requests')
->where('id', $id)
->update([
'status' => 'approved',
'reviewed_by' => (int) $request->user()->id,
'reviewed_at' => now(),
'review_note' => (string) $request->input('note', ''),
'updated_at' => now(),
]);
if ((string) $row->context === 'profile_update' && ! empty($row->user_id)) {
$this->applyProfileRename((int) $row->user_id, (string) $row->requested_username);
}
DB::commit();
} catch (\Throwable $e) {
DB::rollBack();
return response()->json(['message' => $e->getMessage()], Response::HTTP_UNPROCESSABLE_ENTITY);
}
return response()->json([
'success' => true,
'id' => $id,
'status' => 'approved',
], Response::HTTP_OK);
}
public function reject(int $id, Request $request): JsonResponse
{
$affected = DB::table('username_approval_requests')
->where('id', $id)
->where('status', 'pending')
->update([
'status' => 'rejected',
'reviewed_by' => (int) $request->user()->id,
'reviewed_at' => now(),
'review_note' => (string) $request->input('note', ''),
'updated_at' => now(),
]);
if ($affected === 0) {
return response()->json(['message' => 'Request not found or not pending.'], Response::HTTP_NOT_FOUND);
}
return response()->json([
'success' => true,
'id' => $id,
'status' => 'rejected',
], Response::HTTP_OK);
}
private function applyProfileRename(int $userId, string $requestedUsername): void
{
$user = User::query()->find($userId);
if (! $user) {
return;
}
$requested = UsernamePolicy::normalize($requestedUsername);
if ($requested === '') {
throw new \RuntimeException('Requested username is invalid.');
}
$exists = User::query()
->whereRaw('LOWER(username) = ?', [$requested])
->where('id', '!=', $userId)
->exists();
if ($exists) {
throw new \RuntimeException('Requested username is already taken.');
}
$old = UsernamePolicy::normalize((string) ($user->username ?? ''));
if ($old === $requested) {
return;
}
$user->username = $requested;
$user->username_changed_at = now();
$user->save();
if ($old !== '') {
DB::table('username_history')->insert([
'user_id' => $userId,
'old_username' => $old,
'changed_at' => now(),
'created_at' => now(),
'updated_at' => now(),
]);
DB::table('username_redirects')->updateOrInsert(
['old_username' => $old],
[
'new_username' => $requested,
'user_id' => $userId,
'created_at' => now(),
'updated_at' => now(),
]
);
}
}
}