feat(api): RequireAuth+RequireProjectAccess middleware, IDOR-scope check/apply по projectID

This commit is contained in:
2026-07-03 20:47:40 +07:00
parent 35ffe73ae3
commit 4533b0ca25
16 changed files with 498 additions and 143 deletions
+3 -20
View File
@@ -1,15 +1,12 @@
package api
import (
"context"
"errors"
"log"
"net/http"
"strings"
"time"
"github.com/google/uuid"
"github.com/vasyakrg/dns-autoresolver/internal/auth"
"github.com/vasyakrg/dns-autoresolver/internal/store"
)
@@ -39,19 +36,6 @@ func normalizeEmail(email string) string {
return strings.ToLower(strings.TrimSpace(email))
}
// ctxKeyUserID is a private context key carrying the authenticated user's ID.
// Task 4's RequireAuth middleware sets it after validating the session
// cookie; handleMe reads it back.
type ctxKeyUserID struct{}
// userIDFromContext extracts the authenticated user ID set by RequireAuth
// (Task 4). Until that middleware is wired in, tests set it directly via
// context.WithValue.
func userIDFromContext(ctx context.Context) (uuid.UUID, bool) {
id, ok := ctx.Value(ctxKeyUserID{}).(uuid.UUID)
return id, ok
}
func setSessionCookie(w http.ResponseWriter, token string, exp time.Time) {
http.SetCookie(w, &http.Cookie{
Name: sessionCookieName, Value: token, Path: "/",
@@ -165,11 +149,10 @@ func (a *API) handleLogout(w http.ResponseWriter, r *http.Request) {
}
// handleMe returns the authenticated caller's identity + default project.
// The user ID comes from the request context, set by Task 4's RequireAuth
// middleware after validating the session cookie (tests set it directly via
// context.WithValue in the interim).
// The user ID comes from the request context, set by RequireAuth after
// validating the session cookie.
func (a *API) handleMe(w http.ResponseWriter, r *http.Request) {
userID, ok := userIDFromContext(r.Context())
userID, ok := userIDFrom(r.Context())
if !ok {
writeErr(w, http.StatusUnauthorized, "authentication required")
return