0c1047d390
- Go backend with SQLite, JWT auth, file CRUD - Vue 3 frontend with split/raw/WYSIWYG editor modes - Markdown preview (marked, GFM) - Formatting toolbar + keyboard shortcuts - File tree with search, create, delete - Light/dark theme toggle - Admin panel (user management) - Preferences (timezone, theme, default mode) - Shared documents section (placeholder) - Export: PDF, HTML, MD - Build daemon (Python, stdlib only) - Build job queue API - Docker deployment
64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"markdownhub/internal/auth"
|
|
)
|
|
|
|
type contextKey string
|
|
|
|
const (
|
|
ctxUserID contextKey = "userID"
|
|
ctxIsAdmin contextKey = "isAdmin"
|
|
)
|
|
|
|
func (s *Server) requireAuth(next http.HandlerFunc) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
tokenStr := extractToken(r)
|
|
if tokenStr == "" {
|
|
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
|
|
return
|
|
}
|
|
userID, isAdmin, err := auth.ValidateToken(tokenStr, s.secret)
|
|
if err != nil || userID == "" {
|
|
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
|
|
return
|
|
}
|
|
ctx := context.WithValue(r.Context(), ctxUserID, userID)
|
|
ctx = context.WithValue(ctx, ctxIsAdmin, isAdmin)
|
|
next(w, r.WithContext(ctx))
|
|
}
|
|
}
|
|
|
|
func (s *Server) requireAdmin(next http.HandlerFunc) http.HandlerFunc {
|
|
return s.requireAuth(func(w http.ResponseWriter, r *http.Request) {
|
|
isAdmin, _ := r.Context().Value(ctxIsAdmin).(bool)
|
|
if !isAdmin {
|
|
http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
|
|
return
|
|
}
|
|
next(w, r)
|
|
})
|
|
}
|
|
|
|
func extractToken(r *http.Request) string {
|
|
// Cookie first
|
|
if c, err := r.Cookie("authToken"); err == nil && c.Value != "" {
|
|
return c.Value
|
|
}
|
|
// Bearer header
|
|
h := r.Header.Get("Authorization")
|
|
if strings.HasPrefix(h, "Bearer ") {
|
|
return h[7:]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getUserID(r *http.Request) string {
|
|
v, _ := r.Context().Value(ctxUserID).(string)
|
|
return v
|
|
}
|