authService->updateProfile(auth('client')->user(), $request->validated()); $user = $result['client']; if (!empty($result['dirty'])) { $this->activityLogger->log( event: 'profile_update', logName: 'Customer', description: "Customer {$user->email} cập nhật thông tin cá nhân: " . implode(', ', array_keys($result['dirty'])), subject: $user, oldValues: $result['old'], newValues: array_diff_key($result['dirty'], array_flip(['password', 'remember_token'])), ); } return response()->json([ 'error' => false, 'message' => 'Cập nhật thông tin thành công', 'data' => [ 'client' => new ClientResource($user), ], ]); } public function updateCccd(ClientUpdateCccdRequest $request) { // Disk private: ảnh chỉ đọc được qua route signed `api.client.cccd`. $frontUrl = $request->file('cmnd_before')->store('cccd', 'local'); $backUrl = $request->file('cmnd_after')->store('cccd', 'local'); $result = $this->authService->updateCccd( auth('client')->user(), $request->validated('cmnd'), $frontUrl, $backUrl, ); $user = $result['client']; if (!empty($result['dirty'])) { $this->activityLogger->log( event: 'cccd_update', logName: 'Customer', description: "Customer {$user->email} cập nhật chứng minh thư", subject: $user, oldValues: $result['old'], newValues: $result['dirty'], ); } return response()->json([ 'error' => false, 'message' => 'Cập nhật chứng minh thư thành công', 'data' => [ 'client' => new ClientResource($user), ], ]); } /** * Trả ảnh CCCD từ disk private. Route yêu cầu chữ ký (signed:relative) nên không cần * Bearer — chữ ký do ClientResource cấp cho đúng chủ tài khoản, hết hạn sau 60 phút. */ public function cccdImage(int $customer, string $side) { $path = Customer::findOrFail($customer)->{$side === 'front' ? 'front_identity_number' : 'back_identity_number'}; abort_unless($path && str_starts_with($path, 'cccd/') && Storage::disk('local')->exists($path), 404); $mime = match (strtolower(pathinfo($path, PATHINFO_EXTENSION))) { 'png' => 'image/png', 'webp' => 'image/webp', default => 'image/jpeg', }; return Storage::disk('local')->response($path, "cccd-{$side}", [ 'Content-Type' => $mime, 'Content-Disposition' => "inline; filename=\"cccd-{$side}\"", 'Cache-Control' => 'private, no-store', ]); } }