Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -57,6 +57,19 @@ type ttlCache struct {
|
||||
m map[string]cacheItem
|
||||
}
|
||||
|
||||
type routeMeta struct {
|
||||
module string
|
||||
action string
|
||||
}
|
||||
|
||||
var routeMetaCache sync.Map
|
||||
|
||||
var routeMetaFallback = map[string]routeMeta{
|
||||
"GET /api/product-images": {module: "order", action: "view"},
|
||||
"GET /api/product-images/{id}/content": {module: "order", action: "view"},
|
||||
"GET /api/product-stock-query-by-attributes": {module: "order", action: "view"},
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 🌍 GLOBAL SCOPE CACHE (for invalidation)
|
||||
// =====================================================
|
||||
@@ -912,35 +925,40 @@ func AuthzGuardByRoute(pg *sql.DB) func(http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// 3️⃣ ROUTE LOOKUP (path + method)
|
||||
// 3️⃣ ROUTE LOOKUP (path + method) with cache+fallback
|
||||
// =====================================================
|
||||
var module, action string
|
||||
routeKey := r.Method + " " + pathTemplate
|
||||
|
||||
err = pg.QueryRow(`
|
||||
SELECT module_code, action
|
||||
FROM mk_sys_routes
|
||||
WHERE path = $1
|
||||
AND method = $2
|
||||
`,
|
||||
pathTemplate,
|
||||
r.Method,
|
||||
).Scan(&module, &action)
|
||||
|
||||
if err != nil {
|
||||
|
||||
log.Printf(
|
||||
"❌ AUTHZ: route not registered: %s %s",
|
||||
r.Method,
|
||||
if cached, ok := routeMetaCache.Load(routeKey); ok {
|
||||
meta := cached.(routeMeta)
|
||||
module, action = meta.module, meta.action
|
||||
} else {
|
||||
err = pg.QueryRow(`
|
||||
SELECT module_code, action
|
||||
FROM mk_sys_routes
|
||||
WHERE path = $1
|
||||
AND method = $2
|
||||
`,
|
||||
pathTemplate,
|
||||
)
|
||||
r.Method,
|
||||
).Scan(&module, &action)
|
||||
|
||||
if pathTemplate == "/api/password/change" {
|
||||
http.Error(w, "password change route permission not found", http.StatusForbidden)
|
||||
if err == nil {
|
||||
routeMetaCache.Store(routeKey, routeMeta{module: module, action: action})
|
||||
} else if fb, ok := routeMetaFallback[routeKey]; ok {
|
||||
module, action = fb.module, fb.action
|
||||
routeMetaCache.Store(routeKey, fb)
|
||||
log.Printf("⚠️ AUTHZ: route lookup fallback used: %s", routeKey)
|
||||
} else if err == sql.ErrNoRows {
|
||||
log.Printf("❌ AUTHZ: route not registered: %s %s", r.Method, pathTemplate)
|
||||
http.Error(w, "route permission not found", http.StatusForbidden)
|
||||
return
|
||||
} else {
|
||||
log.Printf("❌ AUTHZ: route lookup db error: %s %s err=%v", r.Method, pathTemplate, err)
|
||||
http.Error(w, "permission lookup failed", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
http.Error(w, "route permission not found", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
|
||||
@@ -12,6 +12,8 @@ var publicPaths = []string{
|
||||
"/api/auth/refresh",
|
||||
"/api/password/forgot",
|
||||
"/api/password/reset",
|
||||
"/api/product-images/",
|
||||
"/uploads/",
|
||||
}
|
||||
|
||||
func GlobalAuthMiddleware(db any, next http.Handler) http.Handler {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -59,6 +60,9 @@ func RequestLogger(next http.Handler) http.Handler {
|
||||
|
||||
log.Printf("⬅️ %s %s | status=%d | %s", r.Method, r.URL.Path, sw.status, time.Since(start))
|
||||
|
||||
// High-frequency endpoints: skip route_access audit to reduce DB/log pressure.
|
||||
skipAudit := r.Method == http.MethodGet && strings.HasPrefix(r.URL.Path, "/api/product-images")
|
||||
|
||||
// ---------- AUDIT (route_access) ----------
|
||||
al := auditlog.ActivityLog{
|
||||
ActionType: "route_access",
|
||||
@@ -95,9 +99,9 @@ func RequestLogger(next http.Handler) http.Handler {
|
||||
al.ErrorMessage = http.StatusText(sw.status)
|
||||
}
|
||||
|
||||
// ✅ ESKİ: auditlog.Write(al)
|
||||
// ✅ YENİ:
|
||||
auditlog.Enqueue(r.Context(), al)
|
||||
if !skipAudit {
|
||||
auditlog.Enqueue(r.Context(), al)
|
||||
}
|
||||
|
||||
if claims == nil {
|
||||
log.Println("⚠️ LOGGER: claims is NIL")
|
||||
|
||||
Reference in New Issue
Block a user