Skip to content

Commit f954603

Browse files
authored
Merge pull request #31 from ChingEnLin/dev
Release
2 parents 141f2c6 + a9a4e0f commit f954603

38 files changed

Lines changed: 6640 additions & 2816 deletions
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Claude Code Review
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
9+
jobs:
10+
claude-review:
11+
if: |
12+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude review')) ||
13+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude review'))
14+
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: read
18+
pull-requests: read
19+
issues: read
20+
id-token: write
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 1
27+
28+
- name: Run Claude Code Review
29+
id: claude-review
30+
uses: anthropics/claude-code-action@v1
31+
with:
32+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
33+
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
34+
plugins: 'code-review@claude-code-plugins'
35+
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
36+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
37+
# or https://code.claude.com/docs/en/cli-reference for available options
38+

.github/workflows/claude.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Claude Code
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request_review_comment:
7+
types: [created]
8+
issues:
9+
types: [opened, assigned]
10+
pull_request_review:
11+
types: [submitted]
12+
13+
jobs:
14+
claude:
15+
if: |
16+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20+
runs-on: ubuntu-latest
21+
permissions:
22+
contents: read
23+
pull-requests: read
24+
issues: read
25+
id-token: write
26+
actions: read # Required for Claude to read CI results on PRs
27+
steps:
28+
- name: Checkout repository
29+
uses: actions/checkout@v4
30+
with:
31+
fetch-depth: 1
32+
33+
- name: Run Claude Code
34+
id: claude
35+
uses: anthropics/claude-code-action@v1
36+
with:
37+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38+
39+
# This is an optional setting that allows Claude to read CI results on PRs
40+
additional_permissions: |
41+
actions: read
42+
43+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44+
# prompt: 'Update the pull request description to include a summary of changes.'
45+
46+
# Optional: Add claude_args to customize behavior and configuration
47+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48+
# or https://code.claude.com/docs/en/cli-reference for available options
49+
# claude_args: '--allowed-tools Bash(gh pr *)'
50+

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,9 @@ deployment_note.txt
5050

5151
# Temporary files
5252
development_plans.txt
53+
54+
# claude files
55+
CLAUDE.md
56+
.claude/settings.local.json
57+
HANDOFF.md
58+
DESIGN_HANDBOOK.md

backend/routes/audit.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from fastapi import APIRouter, Header, Body, HTTPException
22
from pydantic import BaseModel
33
from typing import List, Dict, Any, Optional
4-
from services.audit_service import process_audit_question
4+
from services.audit_service import process_audit_question, get_recent_activity
55
from services.gemini_service import VisualizationConfig
6+
from services.user_queries_service import get_user_id_from_token
67

78
router = APIRouter()
89

@@ -18,16 +19,29 @@ class AuditQueryResponse(BaseModel):
1819
visualization: Optional[VisualizationConfig] = None
1920

2021

22+
class RecentActivityItem(BaseModel):
23+
database_name: str
24+
collection_name: str
25+
operation: str
26+
document_id: str
27+
user_email: str
28+
timestamp_utc: str
29+
30+
2131
@router.post("/query", response_model=AuditQueryResponse)
2232
def query_audit_log(
2333
body: AuditQueryRequest = Body(...), authorization: str = Header(...)
2434
):
2535
if not authorization.startswith("Bearer "):
2636
raise HTTPException(status_code=401, detail="Invalid token format")
2737

28-
# We might want to validate the token here even if we don't use it for the pg connection directly yet
29-
# user_token = authorization.replace("Bearer ", "")
30-
# access_token = exchange_token_obo(user_token)
31-
3238
response = process_audit_question(body.question)
3339
return AuditQueryResponse(**response)
40+
41+
42+
@router.get("/recent", response_model=List[RecentActivityItem])
43+
def recent_activity(authorization: str = Header(...), limit: int = 10):
44+
if not authorization.startswith("Bearer "):
45+
raise HTTPException(status_code=401, detail="Invalid token format")
46+
user_email = get_user_id_from_token(authorization.replace("Bearer ", ""))
47+
return get_recent_activity(user_email=user_email, limit=min(limit, 50))

backend/services/audit_service.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Dict, Any
1+
from typing import Dict, Any, List
22
from services.pg_connection import get_connection
33
from services.gemini_service import generate_audit_sql, summarize_audit_results
44

@@ -36,6 +36,36 @@ def execute_audit_query(sql_query: str) -> list:
3636
return [{"error": str(e)}]
3737

3838

39+
def get_recent_activity(user_email: str, limit: int = 10) -> List[Dict[str, Any]]:
40+
"""Returns the most recent write_audit_log rows for a specific user."""
41+
try:
42+
conn = get_connection()
43+
cur = conn.cursor()
44+
cur.execute(
45+
"""
46+
SELECT user_email, operation, database_name, collection_name, document_id, timestamp_utc
47+
FROM write_audit_log
48+
WHERE user_email = %s
49+
ORDER BY timestamp_utc DESC
50+
LIMIT %s
51+
""",
52+
(user_email, limit),
53+
)
54+
columns = [desc[0] for desc in cur.description]
55+
rows = []
56+
for row in cur.fetchall():
57+
item = dict(zip(columns, row))
58+
if hasattr(item.get("timestamp_utc"), "isoformat"):
59+
item["timestamp_utc"] = item["timestamp_utc"].isoformat()
60+
rows.append(item)
61+
cur.close()
62+
conn.close()
63+
return rows
64+
except Exception as e:
65+
print(f"Error fetching recent activity: {e}")
66+
return []
67+
68+
3969
def process_audit_question(question: str) -> Dict[str, Any]:
4070
"""
4171
Orchestrates the process of answering a user's audit question:

backend/services/react_agent_service.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
from services.gemini_service import extract_python_code
2222
from services.mongo_service import execute_mongo_query, transform_mongo_result
2323

24-
2524
WRITE_METHODS = {
2625
"insert_one",
2726
"insert_many",

0 commit comments

Comments
 (0)