215 lines
6 KiB
PHP
215 lines
6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\Api\Admin;
|
|
|
|
use App\Constants\ErrorCode;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Admin;
|
|
use App\Models\Client;
|
|
use App\Services\Auth\TokenService;
|
|
use App\Services\LogService;
|
|
use App\Traits\ApiResponse;
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Redis;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class ClientController extends Controller
|
|
{
|
|
use ApiResponse;
|
|
|
|
private Admin $admin;
|
|
|
|
public function __construct(
|
|
private readonly TokenService $tokenService,
|
|
private readonly LogService $logService,
|
|
Request $request
|
|
) {
|
|
$this->admin = $request->admin;
|
|
}
|
|
|
|
/**
|
|
* 檢查客戶是否有活躍的令牌
|
|
*/
|
|
private function hasActiveTokens(Client $client): bool
|
|
{
|
|
$pattern = 'auth_token:*';
|
|
$keys = Redis::keys($pattern);
|
|
|
|
foreach ($keys as $key) {
|
|
$data = Redis::get($key);
|
|
if ($data) {
|
|
$tokenData = json_decode($data, true);
|
|
if ($tokenData &&
|
|
$tokenData['client_id'] === $client->id &&
|
|
now()->isBefore($tokenData['expires_at'])) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 停用客戶
|
|
*/
|
|
public function deactivate(int $id): JsonResponse
|
|
{
|
|
try {
|
|
$client = Client::findOrFail($id);
|
|
|
|
if (!$this->admin->canManageClient($client->id)) {
|
|
return $this->error(
|
|
ErrorCode::FORBIDDEN,
|
|
'您無權管理該客戶。'
|
|
);
|
|
}
|
|
|
|
if ($this->hasActiveTokens($client)) {
|
|
return $this->error(
|
|
ErrorCode::CLIENT_HAS_ACTIVE_TOKENS,
|
|
'該客戶有活躍的認證令牌,無法停用。'
|
|
);
|
|
}
|
|
|
|
$client->update(['status' => Client::STATUS_INACTIVE]);
|
|
|
|
$this->logService->logOperation(
|
|
'admin',
|
|
$this->admin->id,
|
|
"Deactivated client: {$client->name}"
|
|
);
|
|
|
|
return $this->success();
|
|
|
|
} catch (ModelNotFoundException $e) {
|
|
return $this->error(
|
|
ErrorCode::CLIENT_NOT_FOUND,
|
|
ErrorCode::getMessage(ErrorCode::CLIENT_NOT_FOUND)
|
|
);
|
|
} catch (\Exception $e) {
|
|
Log::error('Error deactivating client', [
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
|
|
return $this->error(
|
|
ErrorCode::SERVER_ERROR,
|
|
ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 刪除客戶
|
|
*/
|
|
public function destroy(int $id): JsonResponse
|
|
{
|
|
try {
|
|
$client = Client::findOrFail($id);
|
|
|
|
if (!$this->admin->canManageClient($client->id)) {
|
|
return $this->error(
|
|
ErrorCode::FORBIDDEN,
|
|
'您無權管理該客戶。'
|
|
);
|
|
}
|
|
|
|
if ($this->hasActiveTokens($client)) {
|
|
return $this->error(
|
|
ErrorCode::CLIENT_HAS_ACTIVE_TOKENS,
|
|
'該客戶有活躍的認證令牌,無法刪除。'
|
|
);
|
|
}
|
|
|
|
$client->delete();
|
|
|
|
$this->logService->logOperation(
|
|
'admin',
|
|
$this->admin->id,
|
|
"Deleted client: {$client->name}"
|
|
);
|
|
|
|
return $this->success();
|
|
|
|
} catch (ModelNotFoundException $e) {
|
|
return $this->error(
|
|
ErrorCode::CLIENT_NOT_FOUND,
|
|
ErrorCode::getMessage(ErrorCode::CLIENT_NOT_FOUND)
|
|
);
|
|
} catch (\Exception $e) {
|
|
Log::error('Error deleting client', [
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
|
|
return $this->error(
|
|
ErrorCode::SERVER_ERROR,
|
|
ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 為客戶生成認證令牌
|
|
*/
|
|
public function generateAuthToken(int $id): JsonResponse
|
|
{
|
|
try {
|
|
$client = Client::findOrFail($id);
|
|
|
|
if (!$this->admin->canManageClient($client->id)) {
|
|
return $this->error(
|
|
ErrorCode::FORBIDDEN,
|
|
'您無權管理該客戶。'
|
|
);
|
|
}
|
|
|
|
if (!$client->isActive()) {
|
|
return $this->error(
|
|
ErrorCode::CLIENT_INACTIVE,
|
|
'客戶未啟用,無法生成令牌。'
|
|
);
|
|
}
|
|
|
|
$token = $this->tokenService->generateAuthToken($client);
|
|
|
|
$this->logService->logOperation(
|
|
'admin',
|
|
$this->admin->id,
|
|
"Generated auth token for client: {$client->name}"
|
|
);
|
|
|
|
return $this->success([
|
|
'auth_token' => $token['token'],
|
|
'expires_at' => $token['expires_at'],
|
|
'client' => [
|
|
'id' => $client->id,
|
|
'name' => $client->name,
|
|
'status' => $client->status,
|
|
],
|
|
]);
|
|
|
|
} catch (ModelNotFoundException $e) {
|
|
return $this->error(
|
|
ErrorCode::CLIENT_NOT_FOUND,
|
|
ErrorCode::getMessage(ErrorCode::CLIENT_NOT_FOUND)
|
|
);
|
|
} catch (\Exception $e) {
|
|
Log::error('Error generating auth token', [
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString(),
|
|
]);
|
|
|
|
return $this->error(
|
|
ErrorCode::SERVER_ERROR,
|
|
ErrorCode::getMessage(ErrorCode::SERVER_ERROR)
|
|
);
|
|
}
|
|
}
|
|
}
|