initial
This commit is contained in:
137
internal/handlers/handlers.go
Normal file
137
internal/handlers/handlers.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"git.eeqj.de/sneak/webhooker/internal/database"
|
||||
"git.eeqj.de/sneak/webhooker/internal/globals"
|
||||
"git.eeqj.de/sneak/webhooker/internal/healthcheck"
|
||||
"git.eeqj.de/sneak/webhooker/internal/logger"
|
||||
"git.eeqj.de/sneak/webhooker/internal/session"
|
||||
"go.uber.org/fx"
|
||||
)
|
||||
|
||||
// nolint:revive // HandlersParams is a standard fx naming convention
|
||||
type HandlersParams struct {
|
||||
fx.In
|
||||
Logger *logger.Logger
|
||||
Globals *globals.Globals
|
||||
Database *database.Database
|
||||
Healthcheck *healthcheck.Healthcheck
|
||||
Session *session.Session
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
params *HandlersParams
|
||||
log *slog.Logger
|
||||
hc *healthcheck.Healthcheck
|
||||
db *database.Database
|
||||
session *session.Session
|
||||
}
|
||||
|
||||
func New(lc fx.Lifecycle, params HandlersParams) (*Handlers, error) {
|
||||
s := new(Handlers)
|
||||
s.params = ¶ms
|
||||
s.log = params.Logger.Get()
|
||||
s.hc = params.Healthcheck
|
||||
s.db = params.Database
|
||||
s.session = params.Session
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
// FIXME compile some templates here or something
|
||||
return nil
|
||||
},
|
||||
})
|
||||
return s, nil
|
||||
}
|
||||
|
||||
//nolint:unparam // r parameter will be used in the future for request context
|
||||
func (s *Handlers) respondJSON(w http.ResponseWriter, r *http.Request, data interface{}, status int) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
if data != nil {
|
||||
err := json.NewEncoder(w).Encode(data)
|
||||
if err != nil {
|
||||
s.log.Error("json encode error", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:unparam,unused // will be used for handling JSON requests
|
||||
func (s *Handlers) decodeJSON(w http.ResponseWriter, r *http.Request, v interface{}) error {
|
||||
return json.NewDecoder(r.Body).Decode(v)
|
||||
}
|
||||
|
||||
// TemplateData represents the common data passed to templates
|
||||
type TemplateData struct {
|
||||
User *UserInfo
|
||||
Version string
|
||||
UserCount int64
|
||||
Uptime string
|
||||
}
|
||||
|
||||
// UserInfo represents user information for templates
|
||||
type UserInfo struct {
|
||||
ID string
|
||||
Username string
|
||||
}
|
||||
|
||||
// renderTemplate renders a template with common data
|
||||
func (s *Handlers) renderTemplate(w http.ResponseWriter, r *http.Request, templateFiles []string, data interface{}) {
|
||||
// Always include the common templates
|
||||
allTemplates := []string{"templates/htmlheader.html", "templates/navbar.html"}
|
||||
allTemplates = append(allTemplates, templateFiles...)
|
||||
|
||||
// Parse templates
|
||||
tmpl, err := template.ParseFiles(allTemplates...)
|
||||
if err != nil {
|
||||
s.log.Error("failed to parse template", "error", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Get user from session if available
|
||||
var userInfo *UserInfo
|
||||
sess, err := s.session.Get(r)
|
||||
if err == nil && s.session.IsAuthenticated(sess) {
|
||||
if username, ok := s.session.GetUsername(sess); ok {
|
||||
if userID, ok := s.session.GetUserID(sess); ok {
|
||||
userInfo = &UserInfo{
|
||||
ID: userID,
|
||||
Username: username,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap data with base template data
|
||||
type templateDataWrapper struct {
|
||||
User *UserInfo
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
wrapper := templateDataWrapper{
|
||||
User: userInfo,
|
||||
Data: data,
|
||||
}
|
||||
|
||||
// If data is a map, merge user info into it
|
||||
if m, ok := data.(map[string]interface{}); ok {
|
||||
m["User"] = userInfo
|
||||
if err := tmpl.Execute(w, m); err != nil {
|
||||
s.log.Error("failed to execute template", "error", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise use wrapper
|
||||
if err := tmpl.Execute(w, wrapper); err != nil {
|
||||
s.log.Error("failed to execute template", "error", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user