142 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
package web
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"net/http"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/gorilla/mux"
 | 
						|
	"github.com/rs/zerolog/log"
 | 
						|
	"github.com/spf13/viper"
 | 
						|
 | 
						|
	"git.coopgo.io/coopgo-apps/parcoursmob/core/application"
 | 
						|
	"git.coopgo.io/coopgo-apps/parcoursmob/renderer"
 | 
						|
	webapi "git.coopgo.io/coopgo-apps/parcoursmob/servers/web/api"
 | 
						|
	webapplication "git.coopgo.io/coopgo-apps/parcoursmob/servers/web/application"
 | 
						|
	webauth "git.coopgo.io/coopgo-apps/parcoursmob/servers/web/auth"
 | 
						|
	webexports "git.coopgo.io/coopgo-apps/parcoursmob/servers/web/exports"
 | 
						|
	webexternal "git.coopgo.io/coopgo-apps/parcoursmob/servers/web/external"
 | 
						|
	webprotectedapi "git.coopgo.io/coopgo-apps/parcoursmob/servers/web/protected_api"
 | 
						|
	"git.coopgo.io/coopgo-apps/parcoursmob/services"
 | 
						|
	"git.coopgo.io/coopgo-apps/parcoursmob/core/utils/identification"
 | 
						|
	cacheStorage "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/storage"
 | 
						|
	"git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
						|
	"github.com/coreos/go-oidc/v3/oidc"
 | 
						|
)
 | 
						|
 | 
						|
type WebServer struct {
 | 
						|
	cfg                 *viper.Viper
 | 
						|
	services            *services.ServicesHandler
 | 
						|
	renderer            *renderer.Renderer
 | 
						|
	applicationHandler  *application.ApplicationHandler
 | 
						|
	exportsHandler      *webexports.Handler
 | 
						|
	authHandler         *webauth.Handler
 | 
						|
	idp                 *identification.IdentificationProvider
 | 
						|
 | 
						|
	// Web handler subpackages
 | 
						|
	appHandler         *webapplication.Handler
 | 
						|
	extHandler         *webexternal.Handler
 | 
						|
	protectedAPIHandler *webprotectedapi.Handler
 | 
						|
	webAPIHandler      *webapi.Handler
 | 
						|
}
 | 
						|
 | 
						|
func Run(cfg *viper.Viper, services *services.ServicesHandler, renderer *renderer.Renderer, applicationHandler *application.ApplicationHandler, idp *identification.IdentificationProvider, cacheHandler cacheStorage.CacheHandler, filestorage cacheStorage.FileStorage) {
 | 
						|
	var (
 | 
						|
		address              = cfg.GetString("server.web.listen")
 | 
						|
		service_name         = cfg.GetString("service_name")
 | 
						|
		templates_public_dir = cfg.GetString("templates.public_dir")
 | 
						|
		dev_env              = cfg.GetBool("dev_env")
 | 
						|
	)
 | 
						|
 | 
						|
	webServer := &WebServer{
 | 
						|
		cfg:                 cfg,
 | 
						|
		services:            services,
 | 
						|
		renderer:            renderer,
 | 
						|
		applicationHandler:  applicationHandler,
 | 
						|
		idp:                 idp,
 | 
						|
 | 
						|
		// Initialize web handler subpackages
 | 
						|
		appHandler:          webapplication.NewHandler(cfg, renderer, applicationHandler, idp, services),
 | 
						|
		authHandler:         webauth.NewHandler(cfg, applicationHandler, idp, renderer),
 | 
						|
		exportsHandler:      webexports.NewHandler(cfg, applicationHandler, idp, renderer),
 | 
						|
		extHandler:          webexternal.NewHandler(cfg, applicationHandler, filestorage),
 | 
						|
		protectedAPIHandler: webprotectedapi.NewHandler(cfg, applicationHandler),
 | 
						|
		webAPIHandler:       webapi.NewHandler(cfg, idp, applicationHandler, cacheHandler),
 | 
						|
	}
 | 
						|
 | 
						|
	r := mux.NewRouter()
 | 
						|
 | 
						|
	// Static files
 | 
						|
	r.PathPrefix("/public/").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir(templates_public_dir))))
 | 
						|
 | 
						|
	// Root redirect
 | 
						|
	r.HandleFunc("/", redirectApp)
 | 
						|
 | 
						|
	// Development middleware
 | 
						|
	if dev_env {
 | 
						|
		r.Use(trackPage)
 | 
						|
	}
 | 
						|
 | 
						|
	// Setup all route groups
 | 
						|
	webServer.setupAuthRoutes(r)
 | 
						|
	webServer.setupCalendarsRoutes(r)
 | 
						|
	webServer.setupExternalRoutes(r)
 | 
						|
	webServer.setupAPIRoutes(r)
 | 
						|
	webServer.setupProtectedAPIRoutes(r)
 | 
						|
	webServer.setupApplicationRoutes(r)
 | 
						|
	webServer.setupExportsRoutes(r)
 | 
						|
 | 
						|
	srv := &http.Server{
 | 
						|
		Handler:      r,
 | 
						|
		Addr:         address,
 | 
						|
		WriteTimeout: 30 * time.Second,
 | 
						|
		ReadTimeout:  15 * time.Second,
 | 
						|
	}
 | 
						|
 | 
						|
	log.Info().Str("service_name", service_name).Str("address", address).Msg("Running HTTP server")
 | 
						|
 | 
						|
	err := srv.ListenAndServe()
 | 
						|
	log.Error().Err(err).Msg("Web server error")
 | 
						|
}
 | 
						|
 | 
						|
func redirectApp(w http.ResponseWriter, r *http.Request) {
 | 
						|
	http.Redirect(w, r, "/app/", http.StatusFound)
 | 
						|
}
 | 
						|
 | 
						|
func trackPage(next http.Handler) http.Handler {
 | 
						|
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
						|
		log.Trace().Str("requested_uri", r.RequestURI).Msg("New request")
 | 
						|
		next.ServeHTTP(w, r.WithContext(r.Context()))
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// Helper functions for extracting user and group information from request context
 | 
						|
func currentGroup(r *http.Request) (current_group storage.Group, err error) {
 | 
						|
	g := r.Context().Value(identification.GroupKey)
 | 
						|
	if g == nil {
 | 
						|
		return storage.Group{}, errors.New("current group not found")
 | 
						|
	}
 | 
						|
	current_group = g.(storage.Group)
 | 
						|
 | 
						|
	return current_group, nil
 | 
						|
}
 | 
						|
 | 
						|
func currentUser(r *http.Request) (current_user_token *oidc.IDToken, current_user_claims map[string]any, err error) {
 | 
						|
	// Get current user ID
 | 
						|
	u := r.Context().Value(identification.IdtokenKey)
 | 
						|
	if u == nil {
 | 
						|
		return nil, nil, errors.New("current user not found")
 | 
						|
	}
 | 
						|
	current_user_token = u.(*oidc.IDToken)
 | 
						|
 | 
						|
	// Get current user claims
 | 
						|
	c := r.Context().Value(identification.ClaimsKey)
 | 
						|
	if c == nil {
 | 
						|
		return current_user_token, nil, errors.New("current user claims not found")
 | 
						|
	}
 | 
						|
	current_user_claims = c.(map[string]any)
 | 
						|
 | 
						|
	return current_user_token, current_user_claims, nil
 | 
						|
}
 | 
						|
 |