repo->paginate($filters, $perPage); } public function get(int $id): ?object { return $this->repo->find($id); } public function create(int $adminId, array $data): array { $code = strtolower(trim((string)($data['code'] ?? ''))); if ($code === '' || !preg_match('/^[a-z0-9\-_]{3,60}$/', $code)) { return ['ok'=>false, 'message'=>'code는 영문/숫자/대시/언더바 3~60자로 입력하세요.']; } // 감사로그용: before/after 구성 (민감정보 없음) $after = [ 'code' => $code, 'title' => trim((string)($data['title'] ?? '')), 'body' => (string)($data['body'] ?? ''), 'description' => trim((string)($data['description'] ?? '')) ?: null, 'is_active' => (int)($data['is_active'] ?? 1), 'created_by' => $adminId, ]; $id = $this->repo->insert($after); // 성공시에만 감사로그 (id가 0/음수면 기록 안 함) if ($id > 0) { $req = request(); $this->audit->log( actorAdminId: $adminId, action: 'admin.template.create', // 네 컨벤션에 맞게 수정 가능 targetType: 'template', // 실제 리소스명에 맞게 targetId: (int)$id, before: null, after: array_merge(['id' => (int)$id], $after), ip: (string)($req?->ip() ?? ''), ua: (string)($req?->userAgent() ?? ''), ); } return ['ok'=>true, 'id'=>$id]; } public function update(int $id, array $data): array { // before 스냅샷(가능하면) — repo에 find/get이 없으면 lockForUpdate 같은 걸로 맞춰야 함 // 여기서는 "repo->find($id)"가 있다고 가정하지 않고, 안전하게 try로 감쌈. $before = null; try { if (method_exists($this->repo, 'find')) { $before = $this->repo->find($id); } elseif (method_exists($this->repo, 'get')) { $before = $this->repo->get($id); } } catch (\Throwable $ignored) { $before = null; } $payload = [ 'title' => trim((string)($data['title'] ?? '')), 'body' => (string)($data['body'] ?? ''), 'description' => trim((string)($data['description'] ?? '')) ?: null, 'is_active' => (int)($data['is_active'] ?? 1), ]; $affected = $this->repo->update($id, $payload); // 기존 리턴 정책 유지 $ok = ($affected >= 0); // 성공시에만 감사로그 if ($ok) { $req = request(); $actorAdminId = (int)(auth('admin')->id() ?? 0); // actorAdminId를 못 구하면 로그 생략(기존 프로그램 방해 X) if ($actorAdminId > 0) { $beforeAudit = $before ? (array)$before : ['id' => $id]; $afterAudit = array_merge($beforeAudit, $payload); $this->audit->log( actorAdminId: $actorAdminId, action: 'admin.template.update', // 네 컨벤션에 맞게 targetType: 'template', targetId: (int)$id, before: $beforeAudit, after: $afterAudit, ip: (string)($req?->ip() ?? ''), ua: (string)($req?->userAgent() ?? ''), ); } } return ['ok'=>$ok]; } public function activeForSend(int $limit = 200): array { return $this->repo->listActive($limit); } }