chore: Enhance CI workflow summary and improve JWT token generation
All checks were successful
CI / skip-ci-check (pull_request) Successful in 1m29s
CI / lint-and-type-check (pull_request) Successful in 2m6s
CI / python-lint (pull_request) Successful in 1m47s
CI / test-backend (pull_request) Successful in 3m8s
CI / build (pull_request) Successful in 2m26s
CI / secret-scanning (pull_request) Successful in 1m43s
CI / dependency-scan (pull_request) Successful in 1m35s
CI / sast-scan (pull_request) Successful in 2m46s
CI / workflow-summary (pull_request) Successful in 1m27s
All checks were successful
CI / skip-ci-check (pull_request) Successful in 1m29s
CI / lint-and-type-check (pull_request) Successful in 2m6s
CI / python-lint (pull_request) Successful in 1m47s
CI / test-backend (pull_request) Successful in 3m8s
CI / build (pull_request) Successful in 2m26s
CI / secret-scanning (pull_request) Successful in 1m43s
CI / dependency-scan (pull_request) Successful in 1m35s
CI / sast-scan (pull_request) Successful in 2m46s
CI / workflow-summary (pull_request) Successful in 1m27s
This commit updates the CI workflow summary to provide a clearer overview of job results and their purposes. It also modifies the JWT token generation in the authentication API to include a unique identifier (`jti`) for both access and refresh tokens, improving token management. Additionally, the test for the token refresh endpoint is adjusted to ensure it verifies the new access token correctly.
This commit is contained in:
parent
70cd7aad95
commit
922c468e9b
@ -506,22 +506,39 @@ jobs:
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
|
||||
if [ "$LEAK_COUNT" -gt 0 ]; then
|
||||
echo "### Leak Details" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "### Leak Summary Table" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| File | Line | Rule | Description | Commit |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "|------|------|------|-------------|--------|" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| File | Line | Rule | Entropy | Commit | Author | Date |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "|------|------|------|---------|--------|--------|------|" >> $GITHUB_STEP_SUMMARY || true
|
||||
|
||||
# Extract and display leak details
|
||||
jq -r '.[] | "| \(.File) | \(.Line) | \(.RuleID) | \(.Description // "N/A") | \(.Commit // "N/A") |"' gitleaks-report.json >> $GITHUB_STEP_SUMMARY || true
|
||||
# Extract and display leak details in table format
|
||||
jq -r '.[] | "| \(.File) | \(.Line) | \(.RuleID) | \(.Entropy // "N/A") | `\(.Commit[0:8])` | \(.Author // "N/A") | \(.Date // "N/A") |"' gitleaks-report.json >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
|
||||
echo "### Detailed Findings" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
|
||||
# Display each finding with full details
|
||||
jq -r '.[] |
|
||||
"#### Finding: \(.RuleID) in \(.File):\(.Line)\n" +
|
||||
"- **File:** `\(.File)`\n" +
|
||||
"- **Line:** \(.Line)\n" +
|
||||
"- **Rule ID:** \(.RuleID)\n" +
|
||||
"- **Description:** \(.Description // "N/A")\n" +
|
||||
"- **Entropy:** \(.Entropy // "N/A")\n" +
|
||||
"- **Commit:** `\(.Commit)`\n" +
|
||||
"- **Author:** \(.Author // "N/A") (\(.Email // "N/A"))\n" +
|
||||
"- **Date:** \(.Date // "N/A")\n" +
|
||||
"- **Fingerprint:** `\(.Fingerprint // "N/A")`\n"' gitleaks-report.json >> $GITHUB_STEP_SUMMARY || true
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "### Full Report (JSON)" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo '```json' >> $GITHUB_STEP_SUMMARY || true
|
||||
cat gitleaks-report.json >> $GITHUB_STEP_SUMMARY || true
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY || true
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "⚠️ **Action Required:** Review and remove the secrets found above." >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "⚠️ **Action Required:** Review and remove the secrets found above. Secrets should be removed from the codebase and rotated if they were ever exposed." >> $GITHUB_STEP_SUMMARY || true
|
||||
else
|
||||
echo "✅ No secrets detected!" >> $GITHUB_STEP_SUMMARY || true
|
||||
fi
|
||||
@ -595,22 +612,36 @@ jobs:
|
||||
steps:
|
||||
- name: Generate workflow summary
|
||||
run: |
|
||||
echo "## 🔍 CI Workflow Summary" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "### Job Results" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 📝 Lint & Type Check | ${{ needs.lint-and-type-check.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 🐍 Python Lint | ${{ needs.python-lint.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 🧪 Backend Tests | ${{ needs.test-backend.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 🏗️ Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 🔐 Secret Scanning | ${{ needs.secret-scanning.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 📦 Dependency Scan | ${{ needs.dependency-scan.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "| 🔍 SAST Scan | ${{ needs.sast-scan.result }} |" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "### 📊 Summary" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "" >> $GITHUB_STEP_SUMMARY || true
|
||||
echo "All security and validation checks have completed." >> $GITHUB_STEP_SUMMARY || true
|
||||
{
|
||||
echo "## 🔍 CI Workflow Summary"
|
||||
echo ""
|
||||
echo "This table gives a **plain-English overview** of what ran in this pipeline and whether it passed."
|
||||
echo ""
|
||||
echo "### Job Results"
|
||||
echo ""
|
||||
echo "| Job | What it does | Status |"
|
||||
echo "|-----|--------------|--------|"
|
||||
echo "| 📝 Lint & Type Check | Runs ESLint on the admin UI and TypeScript type-checks the viewer UI | ${{ needs.lint-and-type-check.result }} |"
|
||||
echo "| 🐍 Python Lint | Runs Python style and syntax checks over the backend | ${{ needs.python-lint.result }} |"
|
||||
echo "| 🧪 Backend Tests | Runs \`pytest tests/ -v\` against the FastAPI backend (with coverage) | ${{ needs.test-backend.result }} |"
|
||||
echo "| 🏗️ Build | Builds the admin frontend (Vite) and viewer frontend (Next.js) | ${{ needs.build.result }} |"
|
||||
echo "| 🔐 Secret Scanning | Uses Gitleaks to look for committed secrets | ${{ needs.secret-scanning.result }} |"
|
||||
echo "| 📦 Dependency Scan | Uses Trivy to scan dependencies for HIGH/CRITICAL vulns | ${{ needs.dependency-scan.result }} |"
|
||||
echo "| 🔍 SAST Scan | Uses Semgrep to look for insecure code patterns | ${{ needs.sast-scan.result }} |"
|
||||
echo ""
|
||||
echo "Legend for the **Status** column:"
|
||||
echo "- \`success\`: job finished and all checks/tests passed."
|
||||
echo "- \`failure\`: job ran but one or more checks/tests failed (see that job's log)."
|
||||
echo "- \`cancelled\`: job was stopped before finishing."
|
||||
echo "- \`skipped\`: job did not run, usually because CI was skipped for this commit."
|
||||
echo ""
|
||||
echo "### 📊 How to read the backend test results"
|
||||
echo ""
|
||||
echo "- The **Backend Tests** row tells you if the test run as a whole passed or failed."
|
||||
echo "- To see which specific tests failed or how they ran:"
|
||||
echo " 1. Open the **test-backend** job in this workflow run."
|
||||
echo " 2. Look at the **Run backend tests** step to see the \`pytest -v\` output."
|
||||
echo " 3. For local debugging, run \`pytest tests/ -v\` in your dev environment."
|
||||
} >> \"${GITHUB_STEP_SUMMARY:-/dev/stdout}\"
|
||||
continue-on-error: true
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import uuid
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Annotated
|
||||
|
||||
@ -87,7 +88,7 @@ def create_access_token(data: dict, expires_delta: timedelta) -> str:
|
||||
"""Create JWT access token."""
|
||||
to_encode = data.copy()
|
||||
expire = datetime.utcnow() + expires_delta
|
||||
to_encode.update({"exp": expire})
|
||||
to_encode.update({"exp": expire, "jti": str(uuid.uuid4())})
|
||||
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
|
||||
|
||||
@ -95,7 +96,7 @@ def create_refresh_token(data: dict) -> str:
|
||||
"""Create JWT refresh token."""
|
||||
to_encode = data.copy()
|
||||
expire = datetime.utcnow() + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)
|
||||
to_encode.update({"exp": expire, "type": "refresh"})
|
||||
to_encode.update({"exp": expire, "type": "refresh", "jti": str(uuid.uuid4())})
|
||||
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
|
||||
|
||||
|
||||
|
||||
@ -126,7 +126,7 @@ class TestTokenRefresh:
|
||||
"""Test token refresh endpoint."""
|
||||
|
||||
def test_refresh_token_success(
|
||||
self, test_client: TestClient, auth_token: str
|
||||
self, test_client: TestClient
|
||||
):
|
||||
"""Verify successful token refresh."""
|
||||
# Get refresh token from login
|
||||
@ -134,7 +134,10 @@ class TestTokenRefresh:
|
||||
"/api/v1/auth/login",
|
||||
json={"username": "testadmin", "password": "testpass"}
|
||||
)
|
||||
refresh_token = login_response.json()["refresh_token"]
|
||||
assert login_response.status_code == 200
|
||||
login_data = login_response.json()
|
||||
initial_access_token = login_data["access_token"]
|
||||
refresh_token = login_data["refresh_token"]
|
||||
|
||||
# Use refresh token to get new access token
|
||||
response = test_client.post(
|
||||
@ -146,7 +149,7 @@ class TestTokenRefresh:
|
||||
data = response.json()
|
||||
assert "access_token" in data
|
||||
assert "refresh_token" in data
|
||||
assert data["access_token"] != auth_token # Should be different token
|
||||
assert data["access_token"] != initial_access_token # Should be different token
|
||||
|
||||
def test_refresh_token_with_invalid_token(self, test_client: TestClient):
|
||||
"""Verify 401 with invalid refresh token."""
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user