mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-28 04:35:40 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			262 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package bootstrap
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"strings"
 | |
| 	"tinyauth/internal/config"
 | |
| 	"tinyauth/internal/controller"
 | |
| 	"tinyauth/internal/middleware"
 | |
| 	"tinyauth/internal/service"
 | |
| 	"tinyauth/internal/utils"
 | |
| 
 | |
| 	"github.com/gin-gonic/gin"
 | |
| 	"github.com/rs/zerolog/log"
 | |
| )
 | |
| 
 | |
| type Controller interface {
 | |
| 	SetupRoutes()
 | |
| }
 | |
| 
 | |
| type Middleware interface {
 | |
| 	Middleware() gin.HandlerFunc
 | |
| 	Init() error
 | |
| }
 | |
| 
 | |
| type Service interface {
 | |
| 	Init() error
 | |
| }
 | |
| 
 | |
| type BootstrapApp struct {
 | |
| 	Config config.Config
 | |
| }
 | |
| 
 | |
| func NewBootstrapApp(config config.Config) *BootstrapApp {
 | |
| 	return &BootstrapApp{
 | |
| 		Config: config,
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (app *BootstrapApp) Setup() error {
 | |
| 	// Parse users
 | |
| 	users, err := utils.GetUsers(app.Config.Users, app.Config.UsersFile)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Get domain
 | |
| 	domain, err := utils.GetUpperDomain(app.Config.AppURL)
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Cookie names
 | |
| 	cookieId := utils.GenerateIdentifier(strings.Split(domain, ".")[0])
 | |
| 	sessionCookieName := fmt.Sprintf("%s-%s", config.SessionCookieName, cookieId)
 | |
| 	csrfCookieName := fmt.Sprintf("%s-%s", config.CSRFCookieName, cookieId)
 | |
| 	redirectCookieName := fmt.Sprintf("%s-%s", config.RedirectCookieName, cookieId)
 | |
| 
 | |
| 	// Create configs
 | |
| 	authConfig := service.AuthServiceConfig{
 | |
| 		Users:             users,
 | |
| 		OauthWhitelist:    app.Config.OAuthWhitelist,
 | |
| 		SessionExpiry:     app.Config.SessionExpiry,
 | |
| 		SecureCookie:      app.Config.SecureCookie,
 | |
| 		Domain:            domain,
 | |
| 		LoginTimeout:      app.Config.LoginTimeout,
 | |
| 		LoginMaxRetries:   app.Config.LoginMaxRetries,
 | |
| 		SessionCookieName: sessionCookieName,
 | |
| 	}
 | |
| 
 | |
| 	// Setup services
 | |
| 	var ldapService *service.LdapService
 | |
| 
 | |
| 	if app.Config.LdapAddress != "" {
 | |
| 		ldapConfig := service.LdapServiceConfig{
 | |
| 			Address:      app.Config.LdapAddress,
 | |
| 			BindDN:       app.Config.LdapBindDN,
 | |
| 			BindPassword: app.Config.LdapBindPassword,
 | |
| 			BaseDN:       app.Config.LdapBaseDN,
 | |
| 			Insecure:     app.Config.LdapInsecure,
 | |
| 			SearchFilter: app.Config.LdapSearchFilter,
 | |
| 		}
 | |
| 
 | |
| 		ldapService = service.NewLdapService(ldapConfig)
 | |
| 
 | |
| 		err := ldapService.Init()
 | |
| 
 | |
| 		if err != nil {
 | |
| 			log.Warn().Err(err).Msg("Failed to initialize LDAP service, continuing without LDAP")
 | |
| 			ldapService = nil
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Bootstrap database
 | |
| 	databaseService := service.NewDatabaseService(service.DatabaseServiceConfig{
 | |
| 		DatabasePath: app.Config.DatabasePath,
 | |
| 	})
 | |
| 
 | |
| 	log.Debug().Str("service", fmt.Sprintf("%T", databaseService)).Msg("Initializing service")
 | |
| 
 | |
| 	err = databaseService.Init()
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to initialize database service: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	database := databaseService.GetDatabase()
 | |
| 
 | |
| 	// Create services
 | |
| 	dockerService := service.NewDockerService()
 | |
| 	authService := service.NewAuthService(authConfig, dockerService, ldapService, database)
 | |
| 	oauthBrokerService := service.NewOAuthBrokerService(app.getOAuthBrokerConfig())
 | |
| 
 | |
| 	// Initialize services
 | |
| 	services := []Service{
 | |
| 		dockerService,
 | |
| 		authService,
 | |
| 		oauthBrokerService,
 | |
| 	}
 | |
| 
 | |
| 	for _, svc := range services {
 | |
| 		if svc != nil {
 | |
| 			log.Debug().Str("service", fmt.Sprintf("%T", svc)).Msg("Initializing service")
 | |
| 			err := svc.Init()
 | |
| 			if err != nil {
 | |
| 				return err
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	// Configured providers
 | |
| 	var configuredProviders []string
 | |
| 
 | |
| 	if authService.UserAuthConfigured() || ldapService != nil {
 | |
| 		configuredProviders = append(configuredProviders, "username")
 | |
| 	}
 | |
| 
 | |
| 	configuredProviders = append(configuredProviders, oauthBrokerService.GetConfiguredServices()...)
 | |
| 
 | |
| 	if len(configuredProviders) == 0 {
 | |
| 		return fmt.Errorf("no authentication providers configured")
 | |
| 	}
 | |
| 
 | |
| 	// Create engine
 | |
| 	engine := gin.New()
 | |
| 
 | |
| 	if config.Version != "development" {
 | |
| 		gin.SetMode(gin.ReleaseMode)
 | |
| 	}
 | |
| 
 | |
| 	// Create middlewares
 | |
| 	var middlewares []Middleware
 | |
| 
 | |
| 	contextMiddleware := middleware.NewContextMiddleware(middleware.ContextMiddlewareConfig{
 | |
| 		Domain: domain,
 | |
| 	}, authService, oauthBrokerService)
 | |
| 
 | |
| 	uiMiddleware := middleware.NewUIMiddleware()
 | |
| 	zerologMiddleware := middleware.NewZerologMiddleware()
 | |
| 
 | |
| 	middlewares = append(middlewares, contextMiddleware, uiMiddleware, zerologMiddleware)
 | |
| 
 | |
| 	for _, middleware := range middlewares {
 | |
| 		log.Debug().Str("middleware", fmt.Sprintf("%T", middleware)).Msg("Initializing middleware")
 | |
| 		err := middleware.Init()
 | |
| 		if err != nil {
 | |
| 			return fmt.Errorf("failed to initialize middleware %T: %w", middleware, err)
 | |
| 		}
 | |
| 		engine.Use(middleware.Middleware())
 | |
| 	}
 | |
| 
 | |
| 	// Create routers
 | |
| 	mainRouter := engine.Group("")
 | |
| 	apiRouter := engine.Group("/api")
 | |
| 
 | |
| 	// Create controllers
 | |
| 	contextController := controller.NewContextController(controller.ContextControllerConfig{
 | |
| 		ConfiguredProviders:   configuredProviders,
 | |
| 		Title:                 app.Config.Title,
 | |
| 		GenericName:           app.Config.GenericName,
 | |
| 		AppURL:                app.Config.AppURL,
 | |
| 		RootDomain:            domain,
 | |
| 		ForgotPasswordMessage: app.Config.ForgotPasswordMessage,
 | |
| 		BackgroundImage:       app.Config.BackgroundImage,
 | |
| 		OAuthAutoRedirect:     app.Config.OAuthAutoRedirect,
 | |
| 	}, apiRouter)
 | |
| 
 | |
| 	oauthController := controller.NewOAuthController(controller.OAuthControllerConfig{
 | |
| 		AppURL:             app.Config.AppURL,
 | |
| 		SecureCookie:       app.Config.SecureCookie,
 | |
| 		CSRFCookieName:     csrfCookieName,
 | |
| 		RedirectCookieName: redirectCookieName,
 | |
| 		Domain:             domain,
 | |
| 	}, apiRouter, authService, oauthBrokerService)
 | |
| 
 | |
| 	proxyController := controller.NewProxyController(controller.ProxyControllerConfig{
 | |
| 		AppURL: app.Config.AppURL,
 | |
| 	}, apiRouter, dockerService, authService)
 | |
| 
 | |
| 	userController := controller.NewUserController(controller.UserControllerConfig{
 | |
| 		Domain: domain,
 | |
| 	}, apiRouter, authService)
 | |
| 
 | |
| 	resourcesController := controller.NewResourcesController(controller.ResourcesControllerConfig{
 | |
| 		ResourcesDir: app.Config.ResourcesDir,
 | |
| 	}, mainRouter)
 | |
| 
 | |
| 	healthController := controller.NewHealthController(apiRouter)
 | |
| 
 | |
| 	// Setup routes
 | |
| 	controller := []Controller{
 | |
| 		contextController,
 | |
| 		oauthController,
 | |
| 		proxyController,
 | |
| 		userController,
 | |
| 		healthController,
 | |
| 		resourcesController,
 | |
| 	}
 | |
| 
 | |
| 	for _, ctrl := range controller {
 | |
| 		log.Debug().Msgf("Setting up %T controller", ctrl)
 | |
| 		ctrl.SetupRoutes()
 | |
| 	}
 | |
| 
 | |
| 	// Start server
 | |
| 	address := fmt.Sprintf("%s:%d", app.Config.Address, app.Config.Port)
 | |
| 	log.Info().Msgf("Starting server on %s", address)
 | |
| 	if err := engine.Run(address); err != nil {
 | |
| 		log.Fatal().Err(err).Msg("Failed to start server")
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Temporary
 | |
| func (app *BootstrapApp) getOAuthBrokerConfig() map[string]config.OAuthServiceConfig {
 | |
| 	return map[string]config.OAuthServiceConfig{
 | |
| 		"google": {
 | |
| 			ClientID:     app.Config.GoogleClientId,
 | |
| 			ClientSecret: app.Config.GoogleClientSecret,
 | |
| 			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/google", app.Config.AppURL),
 | |
| 		},
 | |
| 		"github": {
 | |
| 			ClientID:     app.Config.GithubClientId,
 | |
| 			ClientSecret: app.Config.GithubClientSecret,
 | |
| 			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/github", app.Config.AppURL),
 | |
| 		},
 | |
| 		"generic": {
 | |
| 			ClientID:           app.Config.GenericClientId,
 | |
| 			ClientSecret:       app.Config.GenericClientSecret,
 | |
| 			RedirectURL:        fmt.Sprintf("%s/api/oauth/callback/generic", app.Config.AppURL),
 | |
| 			Scopes:             strings.Split(app.Config.GenericScopes, ","),
 | |
| 			AuthURL:            app.Config.GenericAuthURL,
 | |
| 			TokenURL:           app.Config.GenericTokenURL,
 | |
| 			UserinfoURL:        app.Config.GenericUserURL,
 | |
| 			InsecureSkipVerify: app.Config.GenericSkipSSL,
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| }
 | 
