206 lines
6.0 KiB
Go
206 lines
6.0 KiB
Go
package handler
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"net/http"
|
|
|
|
"dealroom/internal/rbac"
|
|
"dealroom/internal/store"
|
|
|
|
"github.com/gorilla/sessions"
|
|
)
|
|
|
|
// Handler contains dependencies for HTTP handlers
|
|
type Handler struct {
|
|
db *sql.DB
|
|
store *store.Store
|
|
rbac *rbac.Engine
|
|
sessions *sessions.CookieStore
|
|
config *Config
|
|
}
|
|
|
|
// Config holds configuration for handlers
|
|
type Config struct {
|
|
BaseURL string
|
|
SessionKey string
|
|
K25APIURL string
|
|
K25APIKey string
|
|
SMTPHost string
|
|
SMTPUser string
|
|
SMTPPass string
|
|
}
|
|
|
|
// New creates a new handler instance
|
|
func New(db *sql.DB, fileStore *store.Store, config *Config) *Handler {
|
|
return &Handler{
|
|
db: db,
|
|
store: fileStore,
|
|
rbac: rbac.New(db),
|
|
sessions: sessions.NewCookieStore([]byte(config.SessionKey)),
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
// RegisterRoutes sets up all HTTP routes
|
|
func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
|
|
// Static files
|
|
mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
|
|
|
|
// Authentication routes
|
|
mux.HandleFunc("/auth/login", h.handleLogin)
|
|
mux.HandleFunc("/auth/verify/", h.handleVerifyLogin)
|
|
mux.HandleFunc("/auth/logout", h.handleLogout)
|
|
mux.HandleFunc("/auth/me", h.handleMe)
|
|
|
|
// Page routes
|
|
mux.HandleFunc("/", h.handleDashboard)
|
|
mux.HandleFunc("/login", h.handleLoginPage)
|
|
mux.HandleFunc("/deal-rooms/", h.handleDealRoom)
|
|
mux.HandleFunc("/documents/", h.handleDocument)
|
|
mux.HandleFunc("/admin", h.requireAuth(h.requireAdmin(h.handleAdmin)))
|
|
mux.HandleFunc("/profile", h.requireAuth(h.handleProfile))
|
|
mux.HandleFunc("/activity", h.requireAuth(h.handleActivity))
|
|
|
|
// API routes
|
|
mux.HandleFunc("/api/deal-rooms", h.requireAuth(h.handleAPIEndpoint("deal-rooms")))
|
|
mux.HandleFunc("/api/deal-rooms/", h.requireAuth(h.handleAPIEndpoint("deal-rooms")))
|
|
mux.HandleFunc("/api/entries", h.requireAuth(h.handleAPIEndpoint("entries")))
|
|
mux.HandleFunc("/api/entries/", h.requireAuth(h.handleAPIEndpoint("entries")))
|
|
mux.HandleFunc("/api/search", h.requireAuth(h.handleSearch))
|
|
mux.HandleFunc("/api/activity/", h.requireAuth(h.handleAPIActivity))
|
|
}
|
|
|
|
// Middleware
|
|
|
|
func (h *Handler) requireAuth(next http.HandlerFunc) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
session, _ := h.sessions.Get(r, "dealroom")
|
|
userID, ok := session.Values["user_id"].(string)
|
|
|
|
if !ok || userID == "" {
|
|
if isAPIRequest(r) {
|
|
http.Error(w, "Authentication required", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
// Add user ID to request context
|
|
ctx := r.Context()
|
|
ctx = setUserID(ctx, userID)
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
}
|
|
}
|
|
|
|
func (h *Handler) requireAdmin(next http.HandlerFunc) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
userID := getUserID(r.Context())
|
|
|
|
// Check if user is admin
|
|
var role string
|
|
err := h.db.QueryRow("SELECT role FROM users WHERE id = ?", userID).Scan(&role)
|
|
if err != nil || role != "admin" {
|
|
http.Error(w, "Admin access required", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
next.ServeHTTP(w, r)
|
|
}
|
|
}
|
|
|
|
// Placeholder handlers - to be implemented
|
|
|
|
func (h *Handler) handleLogin(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Implement magic link login
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleVerifyLogin(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Implement login verification
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleLogout(w http.ResponseWriter, r *http.Request) {
|
|
session, _ := h.sessions.Get(r, "dealroom")
|
|
session.Values["user_id"] = ""
|
|
session.Save(r, w)
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
}
|
|
|
|
func (h *Handler) handleMe(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Return current user info
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleDashboard(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Render dashboard template
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleLoginPage(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Render login template
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleDealRoom(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Handle deal room pages
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleDocument(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Handle document viewing
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleAdmin(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Render admin panel
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleProfile(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Render user profile
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleActivity(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Render activity feed
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleAPIEndpoint(endpoint string) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Implement REST API endpoints
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
}
|
|
|
|
func (h *Handler) handleSearch(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Implement search API
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *Handler) handleAPIActivity(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: Implement activity API
|
|
http.Error(w, "Not implemented", http.StatusNotImplemented)
|
|
}
|
|
|
|
// Helper functions
|
|
|
|
func isAPIRequest(r *http.Request) bool {
|
|
return r.Header.Get("Accept") == "application/json" ||
|
|
r.Header.Get("Content-Type") == "application/json" ||
|
|
r.URL.Path[:5] == "/api/"
|
|
}
|
|
|
|
// Context helpers would go in a separate context.go file
|
|
func setUserID(ctx context.Context, userID string) context.Context {
|
|
// TODO: Implement context helpers
|
|
return ctx
|
|
}
|
|
|
|
func getUserID(ctx context.Context) string {
|
|
// TODO: Implement context helpers
|
|
return ""
|
|
} |