Initial commit: Phase 1+2 prototype
- 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
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user