get('userid')) { return $this->respond([ 'status' => 'error', 'message' => 'Unauthorized', ], 401); } return null; } private function ensureAdmin() { $level = (int) session()->get('level'); if (!in_array($level, [0, 1, 2], true)) { return $this->respond([ 'status' => 'error', 'message' => 'Forbidden. Admin only.', ], 403); } return null; } public function summary() { if ($response = $this->ensureLoggedIn()) { return $response; } $db = \Config\Database::connect(); $usersCount = $db->table('git_users')->countAllResults(); $repositoriesCount = $db->table('git_repositories')->countAllResults(); $commitsCount = $db->table('git_commits')->countAllResults(); $pullRequestsCount = $db->table('git_pull_requests')->countAllResults(); $latestCommit = $db->table('git_commits')->selectMax('committed_at', 'latest')->get()->getRowArray(); $latestPullRequest = $db->table('git_pull_requests')->selectMax('updated_at_gitea', 'latest')->get()->getRowArray(); $latestRepoSync = $db->table('git_repositories')->selectMax('last_synced_at', 'latest')->get()->getRowArray(); return $this->respond([ 'status' => 'success', 'message' => 'Summary fetched', 'data' => [ 'users' => $usersCount, 'repositories' => $repositoriesCount, 'commits' => $commitsCount, 'pull_requests' => $pullRequestsCount, 'latest_commit_at' => $latestCommit['latest'] ?? null, 'latest_pull_request_at' => $latestPullRequest['latest'] ?? null, 'last_synced_at' => $latestRepoSync['latest'] ?? null, ], ], 200); } public function users() { if ($response = $this->ensureLoggedIn()) { return $response; } $db = \Config\Database::connect(); $rows = $db->table('git_users') ->select('id, gitea_user_id, username, full_name, email, is_active, is_admin, last_synced_at') ->orderBy('username', 'ASC') ->get() ->getResultArray(); return $this->respond([ 'status' => 'success', 'message' => 'Users fetched', 'data' => $rows, ], 200); } public function repositories() { if ($response = $this->ensureLoggedIn()) { return $response; } $db = \Config\Database::connect(); $rows = $db->table('git_repositories r') ->select('r.id, r.gitea_repo_id, r.name, r.full_name, r.owner_username, r.default_branch, r.is_private, r.last_pushed_at, r.last_synced_at, u.username as owner_login') ->join('git_users u', 'u.id = r.owner_user_id', 'left') ->orderBy('r.full_name', 'ASC') ->get() ->getResultArray(); return $this->respond([ 'status' => 'success', 'message' => 'Repositories fetched', 'data' => $rows, ], 200); } public function commits() { if ($response = $this->ensureLoggedIn()) { return $response; } $repoId = $this->request->getGet('repo_id'); $userId = $this->request->getGet('user_id'); $startDate = $this->request->getGet('start_date'); $endDate = $this->request->getGet('end_date'); $limit = (int) ($this->request->getGet('limit') ?? 200); if ($limit <= 0 || $limit > 1000) { $limit = 200; } $db = \Config\Database::connect(); $builder = $db->table('git_commits c') ->select('c.id, c.sha, c.short_sha, c.message, c.author_name, c.author_email, c.committed_at, c.html_url, r.id as repository_id, r.full_name as repository_full_name, u.id as user_id, u.username as user_username') ->join('git_repositories r', 'r.id = c.repository_id', 'inner') ->join('git_users u', 'u.id = c.author_user_id', 'left'); if (!empty($repoId)) { $builder->where('c.repository_id', (int) $repoId); } if (!empty($userId)) { $builder->where('c.author_user_id', (int) $userId); } if (!empty($startDate)) { $builder->where('c.committed_at >=', $startDate . ' 00:00:00'); } if (!empty($endDate)) { $builder->where('c.committed_at <=', $endDate . ' 23:59:59'); } $rows = $builder ->orderBy('c.committed_at', 'DESC') ->limit($limit) ->get() ->getResultArray(); return $this->respond([ 'status' => 'success', 'message' => 'Commits fetched', 'data' => $rows, ], 200); } public function pullRequests() { if ($response = $this->ensureLoggedIn()) { return $response; } $repoId = $this->request->getGet('repo_id'); $userId = $this->request->getGet('user_id'); $state = $this->request->getGet('state'); $startDate = $this->request->getGet('start_date'); $endDate = $this->request->getGet('end_date'); $limit = (int) ($this->request->getGet('limit') ?? 200); if ($limit <= 0 || $limit > 1000) { $limit = 200; } $db = \Config\Database::connect(); $builder = $db->table('git_pull_requests p') ->select('p.id, p.number, p.title, p.state, p.is_draft, p.is_merged, p.created_at_gitea, p.updated_at_gitea, p.merged_at, p.closed_at, p.html_url, r.id as repository_id, r.full_name as repository_full_name, u.id as user_id, u.username as user_username') ->join('git_repositories r', 'r.id = p.repository_id', 'inner') ->join('git_users u', 'u.id = p.author_user_id', 'left'); if (!empty($repoId)) { $builder->where('p.repository_id', (int) $repoId); } if (!empty($userId)) { $builder->where('p.author_user_id', (int) $userId); } if (!empty($state)) { $builder->where('p.state', $state); } if (!empty($startDate)) { $builder->where('p.updated_at_gitea >=', $startDate . ' 00:00:00'); } if (!empty($endDate)) { $builder->where('p.updated_at_gitea <=', $endDate . ' 23:59:59'); } $rows = $builder ->orderBy('p.updated_at_gitea', 'DESC') ->limit($limit) ->get() ->getResultArray(); return $this->respond([ 'status' => 'success', 'message' => 'Pull requests fetched', 'data' => $rows, ], 200); } public function sync() { if ($response = $this->ensureLoggedIn()) { return $response; } if ($response = $this->ensureAdmin()) { return $response; } $service = new GiteaSyncService(); $result = $service->syncAll(); $statusCode = $result['success'] ? 200 : 500; return $this->respond([ 'status' => $result['success'] ? 'success' : 'error', 'message' => $result['message'], 'data' => $result['stats'] ?? [], ], $statusCode); } }