79 lines
2.1 KiB
Go
79 lines
2.1 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"xorm.io/xorm"
|
|
|
|
"github.com/forgeo/forgebucket/internal/api/middleware"
|
|
"github.com/forgeo/forgebucket/internal/domain/scanning"
|
|
"github.com/forgeo/forgebucket/internal/models"
|
|
)
|
|
|
|
type ScanningHandler struct {
|
|
db *xorm.Engine
|
|
scanner *scanning.Scanner
|
|
}
|
|
|
|
func NewScanningHandler(db *xorm.Engine, scanner *scanning.Scanner) *ScanningHandler {
|
|
return &ScanningHandler{db: db, scanner: scanner}
|
|
}
|
|
|
|
// ListSecrets returns all active (non-dismissed) secret leaks for a repo.
|
|
// GET /api/v1/repos/{owner}/{repo}/secrets/leaks
|
|
func (h *ScanningHandler) ListSecrets(w http.ResponseWriter, r *http.Request) {
|
|
repoID, ok := resolveRepoID(h.db, w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
leaks, err := h.scanner.ListFindings(repoID)
|
|
if err != nil {
|
|
jsonError(w, "database error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
jsonOK(w, leaks)
|
|
}
|
|
|
|
// DismissSecrets acknowledges a leak so it no longer appears in active lists.
|
|
// POST /api/v1/repos/{owner}/{repo}/secrets/leaks/{leakID}/dismiss
|
|
func (h *ScanningHandler) DismissSecrets(w http.ResponseWriter, r *http.Request) {
|
|
repoID, ok := resolveRepoID(h.db, w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
_ = repoID
|
|
|
|
leakID, err := strconv.ParseInt(chi.URLParam(r, "leakID"), 10, 64)
|
|
if err != nil {
|
|
jsonError(w, "invalid leak ID", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Get current user from session for audit trail.
|
|
username, _ := r.Context().Value(middleware.ContextKeyUsername).(string)
|
|
|
|
if err := h.scanner.DismissFindings(leakID, username); err != nil {
|
|
jsonError(w, err.Error(), http.StatusNotFound)
|
|
return
|
|
}
|
|
jsonOK(w, map[string]string{"status": "dismissed"})
|
|
}
|
|
|
|
// ListAllSecrets returns active leaks across all repos (admin/workspace).
|
|
// GET /api/v1/secrets/leaks
|
|
func (h *ScanningHandler) ListAllSecrets(w http.ResponseWriter, r *http.Request) {
|
|
var leaks []models.SecretLeak
|
|
if err := h.db.Where("dismissed = ?", false).
|
|
OrderBy("detected_at DESC").Find(&leaks); err != nil {
|
|
jsonError(w, "database error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if leaks == nil {
|
|
leaks = []models.SecretLeak{}
|
|
}
|
|
jsonOK(w, leaks)
|
|
}
|