PunimTag Web Application - Major Feature Release #1
@ -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