Add public theme
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 2m52s

This commit is contained in:
Arnaud Delcasse
2026-01-30 18:44:17 +01:00
parent 2333bba79b
commit b5e722ff9b
23 changed files with 249 additions and 112 deletions

64
servers/publicweb/api.go Normal file
View File

@@ -0,0 +1,64 @@
package publicweb
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/rs/zerolog/log"
)
func (s *PublicWebServer) setupAPIRoutes(r *mux.Router) {
api := r.PathPrefix("/api").Subrouter()
api.HandleFunc("/contact", s.contactHandler).Methods("POST", "OPTIONS")
}
func (s *PublicWebServer) contactHandler(w http.ResponseWriter, r *http.Request) {
// Handle CORS preflight
if r.Method == "OPTIONS" {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
w.WriteHeader(http.StatusOK)
return
}
var data map[string]any
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
log.Error().Err(err).Msg("Failed to decode contact request")
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
if len(data) == 0 {
http.Error(w, "Request body cannot be empty", http.StatusBadRequest)
return
}
// Structure data for email template
emailData := map[string]any{
"baseUrl": s.cfg.GetString("base_url"),
"fields": data,
}
// Send email using the mailer
contactEmail := s.cfg.GetString("server.publicweb.contact_email")
if contactEmail == "" {
log.Error().Msg("Contact email not configured")
http.Error(w, "Contact service not configured", http.StatusInternalServerError)
return
}
if err := s.mailer.Send("contact.request", contactEmail, emailData); err != nil {
log.Error().Err(err).Msg("Failed to send contact email")
http.Error(w, "Failed to send message", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{
"status": "success",
"message": "Message sent successfully",
})
}

View File

@@ -16,6 +16,7 @@ import (
"git.coopgo.io/coopgo-apps/parcoursmob/core/application"
cache "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/storage"
"git.coopgo.io/coopgo-apps/parcoursmob/services"
"git.coopgo.io/coopgo-platform/emailing"
)
// DataProvider returns data to hydrate a page
@@ -36,6 +37,7 @@ type PublicWebServer struct {
kv cache.KVHandler
filestorage cache.FileStorage
applicationHandler *application.ApplicationHandler
mailer *emailing.Mailer
rootDir string
dynamicRoutes map[string]DynamicRoute
}
@@ -46,6 +48,7 @@ func Run(
applicationHandler *application.ApplicationHandler,
kv cache.KVHandler,
filestorage cache.FileStorage,
mailer *emailing.Mailer,
) {
address := cfg.GetString("server.publicweb.listen")
rootDir := cfg.GetString("server.publicweb.root_dir")
@@ -57,6 +60,7 @@ func Run(
kv: kv,
filestorage: filestorage,
applicationHandler: applicationHandler,
mailer: mailer,
rootDir: rootDir,
dynamicRoutes: make(map[string]DynamicRoute),
}
@@ -67,6 +71,9 @@ func Run(
r.HandleFunc("/health", server.healthHandler).Methods("GET")
// Setup API routes
server.setupAPIRoutes(r)
for pattern := range server.dynamicRoutes {
r.HandleFunc(pattern, server.dynamicHandler).Methods("GET", "POST")
}

View File

@@ -222,7 +222,7 @@ func (h *Handler) AdminStatsBookingsHTTPHandler() http.HandlerFunc {
func (h *Handler) AdminStatsBeneficiariesHTTPHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
result, err := h.applicationHandler.GetBeneficiariesStats()
result, err := h.applicationHandler.GetBeneficiariesStats(r.Context())
if err != nil {
log.Error().Err(err).Msg("error retrieving beneficiaries stats")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)

View File

@@ -59,7 +59,7 @@ func (h *Handler) JourneysSearchHTTPHandler() http.HandlerFunc {
var departureGeo *geojson.Feature
if departure == "" && passengerID != "" {
// Get passenger address
p, err := h.services.GetAccount(passengerID)
p, err := h.services.GetAccount(r.Context(), passengerID)
if err != nil {
log.Error().Err(err).Msg("could not retrieve passenger")
http.Error(w, "Not Found", http.StatusNotFound)
@@ -123,7 +123,7 @@ func (h *Handler) JourneysSearchHTTPHandler() http.HandlerFunc {
}
group := g.(groupstorage.Group)
beneficiaries, err := h.services.GetBeneficiariesInGroup(group)
beneficiaries, err := h.services.GetBeneficiariesInGroup(r.Context(), group)
if err != nil {
log.Error().Err(err).Msg("issue retrieving beneficiaries")
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
@@ -345,7 +345,7 @@ func (h *Handler) JourneysSearchCompactHTTPHandler() http.HandlerFunc {
var departureGeo *geojson.Feature
if departure == "" && passengerID != "" {
// Get passenger address
p, err := h.services.GetAccount(passengerID)
p, err := h.services.GetAccount(r.Context(), passengerID)
if err != nil {
log.Error().Err(err).Msg("could not retrieve passenger")
http.Error(w, "Not Found", http.StatusNotFound)

View File

@@ -89,8 +89,8 @@ func Run(cfg *viper.Viper, services *services.ServicesHandler, renderer *rendere
srv := &http.Server{
Handler: r,
Addr: address,
WriteTimeout: 30 * time.Second,
ReadTimeout: 15 * time.Second,
WriteTimeout: 120 * time.Second,
ReadTimeout: 30 * time.Second,
}
log.Info().Str("service_name", service_name).Str("address", address).Msg("Running HTTP server")