mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-11-03 23:55:44 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v3.6.2
			...
			refactor/r
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					59d2bce189 | 
							
								
								
									
										28
									
								
								cmd/root.go
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								cmd/root.go
									
									
									
									
									
								
							@@ -8,13 +8,13 @@ import (
 | 
			
		||||
	"time"
 | 
			
		||||
	totpCmd "tinyauth/cmd/totp"
 | 
			
		||||
	userCmd "tinyauth/cmd/user"
 | 
			
		||||
	"tinyauth/internal/api"
 | 
			
		||||
	"tinyauth/internal/auth"
 | 
			
		||||
	"tinyauth/internal/constants"
 | 
			
		||||
	"tinyauth/internal/docker"
 | 
			
		||||
	"tinyauth/internal/handlers"
 | 
			
		||||
	"tinyauth/internal/hooks"
 | 
			
		||||
	"tinyauth/internal/providers"
 | 
			
		||||
	"tinyauth/internal/server"
 | 
			
		||||
	"tinyauth/internal/types"
 | 
			
		||||
	"tinyauth/internal/utils"
 | 
			
		||||
 | 
			
		||||
@@ -114,8 +114,8 @@ var rootCmd = &cobra.Command{
 | 
			
		||||
			RedirectCookieName:    redirectCookieName,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Create api config
 | 
			
		||||
		apiConfig := types.APIConfig{
 | 
			
		||||
		// Create server config
 | 
			
		||||
		serverConfig := types.ServerConfig{
 | 
			
		||||
			Port:    config.Port,
 | 
			
		||||
			Address: config.Address,
 | 
			
		||||
		}
 | 
			
		||||
@@ -140,10 +140,7 @@ var rootCmd = &cobra.Command{
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Create docker service
 | 
			
		||||
		docker := docker.NewDocker()
 | 
			
		||||
 | 
			
		||||
		// Initialize docker
 | 
			
		||||
		err = docker.Init()
 | 
			
		||||
		docker, err := docker.NewDocker()
 | 
			
		||||
		HandleError(err, "Failed to initialize docker")
 | 
			
		||||
 | 
			
		||||
		// Create auth service
 | 
			
		||||
@@ -152,24 +149,19 @@ var rootCmd = &cobra.Command{
 | 
			
		||||
		// Create OAuth providers service
 | 
			
		||||
		providers := providers.NewProviders(oauthConfig)
 | 
			
		||||
 | 
			
		||||
		// Initialize providers
 | 
			
		||||
		providers.Init()
 | 
			
		||||
 | 
			
		||||
		// Create hooks service
 | 
			
		||||
		hooks := hooks.NewHooks(hooksConfig, auth, providers)
 | 
			
		||||
 | 
			
		||||
		// Create handlers
 | 
			
		||||
		handlers := handlers.NewHandlers(handlersConfig, auth, hooks, providers, docker)
 | 
			
		||||
 | 
			
		||||
		// Create API
 | 
			
		||||
		api := api.NewAPI(apiConfig, handlers)
 | 
			
		||||
		// Create server
 | 
			
		||||
		srv, err := server.NewServer(serverConfig, handlers)
 | 
			
		||||
		HandleError(err, "Failed to create server")
 | 
			
		||||
 | 
			
		||||
		// Setup routes
 | 
			
		||||
		api.Init()
 | 
			
		||||
		api.SetupRoutes()
 | 
			
		||||
 | 
			
		||||
		// Start
 | 
			
		||||
		api.Run()
 | 
			
		||||
		// Start server
 | 
			
		||||
		err = srv.Start()
 | 
			
		||||
		HandleError(err, "Failed to start server")
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,36 +16,38 @@ import (
 | 
			
		||||
	"golang.org/x/crypto/bcrypt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewAuth(config types.AuthConfig, docker *docker.Docker) *Auth {
 | 
			
		||||
	return &Auth{
 | 
			
		||||
		Config:        config,
 | 
			
		||||
		Docker:        docker,
 | 
			
		||||
		LoginAttempts: make(map[string]*types.LoginAttempt),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Auth struct {
 | 
			
		||||
	Config        types.AuthConfig
 | 
			
		||||
	Docker        *docker.Docker
 | 
			
		||||
	LoginAttempts map[string]*types.LoginAttempt
 | 
			
		||||
	LoginMutex    sync.RWMutex
 | 
			
		||||
	Store         *sessions.CookieStore
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) {
 | 
			
		||||
func NewAuth(config types.AuthConfig, docker *docker.Docker) *Auth {
 | 
			
		||||
	// Create cookie store
 | 
			
		||||
	store := sessions.NewCookieStore([]byte(auth.Config.HMACSecret), []byte(auth.Config.EncryptionSecret))
 | 
			
		||||
	store := sessions.NewCookieStore([]byte(config.HMACSecret), []byte(config.EncryptionSecret))
 | 
			
		||||
 | 
			
		||||
	// Configure cookie store
 | 
			
		||||
	store.Options = &sessions.Options{
 | 
			
		||||
		Path:     "/",
 | 
			
		||||
		MaxAge:   auth.Config.SessionExpiry,
 | 
			
		||||
		Secure:   auth.Config.CookieSecure,
 | 
			
		||||
		MaxAge:   config.SessionExpiry,
 | 
			
		||||
		Secure:   config.CookieSecure,
 | 
			
		||||
		HttpOnly: true,
 | 
			
		||||
		Domain:   fmt.Sprintf(".%s", auth.Config.Domain),
 | 
			
		||||
		Domain:   fmt.Sprintf(".%s", config.Domain),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Auth{
 | 
			
		||||
		Config:        config,
 | 
			
		||||
		Docker:        docker,
 | 
			
		||||
		LoginAttempts: make(map[string]*types.LoginAttempt),
 | 
			
		||||
		Store:         store,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) {
 | 
			
		||||
	// Get session
 | 
			
		||||
	session, err := store.Get(c.Request, auth.Config.SessionCookieName)
 | 
			
		||||
	session, err := auth.Store.Get(c.Request, auth.Config.SessionCookieName)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Warn().Err(err).Msg("Invalid session, clearing cookie and retrying")
 | 
			
		||||
@@ -54,7 +56,7 @@ func (auth *Auth) GetSession(c *gin.Context) (*sessions.Session, error) {
 | 
			
		||||
		c.SetCookie(auth.Config.SessionCookieName, "", -1, "/", fmt.Sprintf(".%s", auth.Config.Domain), auth.Config.CookieSecure, true)
 | 
			
		||||
 | 
			
		||||
		// Try to get the session again
 | 
			
		||||
		session, err = store.Get(c.Request, auth.Config.SessionCookieName)
 | 
			
		||||
		session, err = auth.Store.Get(c.Request, auth.Config.SessionCookieName)
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			// If we still can't get the session, log the error and return nil
 | 
			
		||||
 
 | 
			
		||||
@@ -11,35 +11,30 @@ import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewDocker() *Docker {
 | 
			
		||||
	return &Docker{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Docker struct {
 | 
			
		||||
	Client  *client.Client
 | 
			
		||||
	Context context.Context
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (docker *Docker) Init() error {
 | 
			
		||||
func NewDocker() (*Docker, error) {
 | 
			
		||||
	// Create a new docker client
 | 
			
		||||
	client, err := client.NewClientWithOpts(client.FromEnv)
 | 
			
		||||
 | 
			
		||||
	// Check if there was an error
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create the context
 | 
			
		||||
	docker.Context = context.Background()
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	// Negotiate API version
 | 
			
		||||
	client.NegotiateAPIVersion(docker.Context)
 | 
			
		||||
	client.NegotiateAPIVersion(ctx)
 | 
			
		||||
 | 
			
		||||
	// Set client
 | 
			
		||||
	docker.Client = client
 | 
			
		||||
 | 
			
		||||
	// Done
 | 
			
		||||
	return nil
 | 
			
		||||
	return &Docker{
 | 
			
		||||
		Client:  client,
 | 
			
		||||
		Context: ctx,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (docker *Docker) GetContainers() ([]container.Summary, error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,14 @@ import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Handlers struct {
 | 
			
		||||
	Config    types.HandlersConfig
 | 
			
		||||
	Auth      *auth.Auth
 | 
			
		||||
	Hooks     *hooks.Hooks
 | 
			
		||||
	Providers *providers.Providers
 | 
			
		||||
	Docker    *docker.Docker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHandlers(config types.HandlersConfig, auth *auth.Auth, hooks *hooks.Hooks, providers *providers.Providers, docker *docker.Docker) *Handlers {
 | 
			
		||||
	return &Handlers{
 | 
			
		||||
		Config:    config,
 | 
			
		||||
@@ -28,14 +36,6 @@ func NewHandlers(config types.HandlersConfig, auth *auth.Auth, hooks *hooks.Hook
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Handlers struct {
 | 
			
		||||
	Config    types.HandlersConfig
 | 
			
		||||
	Auth      *auth.Auth
 | 
			
		||||
	Hooks     *hooks.Hooks
 | 
			
		||||
	Providers *providers.Providers
 | 
			
		||||
	Docker    *docker.Docker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handlers) AuthHandler(c *gin.Context) {
 | 
			
		||||
	// Create struct for proxy
 | 
			
		||||
	var proxy types.Proxy
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,12 @@ import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Hooks struct {
 | 
			
		||||
	Config    types.HooksConfig
 | 
			
		||||
	Auth      *auth.Auth
 | 
			
		||||
	Providers *providers.Providers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewHooks(config types.HooksConfig, auth *auth.Auth, providers *providers.Providers) *Hooks {
 | 
			
		||||
	return &Hooks{
 | 
			
		||||
		Config:    config,
 | 
			
		||||
@@ -20,12 +26,6 @@ func NewHooks(config types.HooksConfig, auth *auth.Auth, providers *providers.Pr
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Hooks struct {
 | 
			
		||||
	Config    types.HooksConfig
 | 
			
		||||
	Auth      *auth.Auth
 | 
			
		||||
	Providers *providers.Providers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (hooks *Hooks) UseUserContext(c *gin.Context) types.UserContext {
 | 
			
		||||
	// Get session cookie and basic auth
 | 
			
		||||
	cookie, err := hooks.Auth.GetSessionCookie(c)
 | 
			
		||||
 
 | 
			
		||||
@@ -10,32 +10,24 @@ import (
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewOAuth(config oauth2.Config, insecureSkipVerify bool) *OAuth {
 | 
			
		||||
	return &OAuth{
 | 
			
		||||
		Config:             config,
 | 
			
		||||
		InsecureSkipVerify: insecureSkipVerify,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type OAuth struct {
 | 
			
		||||
	Config             oauth2.Config
 | 
			
		||||
	Context            context.Context
 | 
			
		||||
	Token              *oauth2.Token
 | 
			
		||||
	Verifier           string
 | 
			
		||||
	InsecureSkipVerify bool
 | 
			
		||||
	Config   oauth2.Config
 | 
			
		||||
	Context  context.Context
 | 
			
		||||
	Token    *oauth2.Token
 | 
			
		||||
	Verifier string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (oauth *OAuth) Init() {
 | 
			
		||||
func NewOAuth(config oauth2.Config, insecureSkipVerify bool) *OAuth {
 | 
			
		||||
	// Create transport with TLS
 | 
			
		||||
	transport := &http.Transport{
 | 
			
		||||
		TLSClientConfig: &tls.Config{
 | 
			
		||||
			InsecureSkipVerify: oauth.InsecureSkipVerify,
 | 
			
		||||
			InsecureSkipVerify: insecureSkipVerify,
 | 
			
		||||
			MinVersion:         tls.VersionTLS12,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create a new context
 | 
			
		||||
	oauth.Context = context.Background()
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
 | 
			
		||||
	// Create the HTTP client with the transport
 | 
			
		||||
	httpClient := &http.Client{
 | 
			
		||||
@@ -43,9 +35,16 @@ func (oauth *OAuth) Init() {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set the HTTP client in the context
 | 
			
		||||
	oauth.Context = context.WithValue(oauth.Context, oauth2.HTTPClient, httpClient)
 | 
			
		||||
	ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
 | 
			
		||||
 | 
			
		||||
	// Create the verifier
 | 
			
		||||
	oauth.Verifier = oauth2.GenerateVerifier()
 | 
			
		||||
	verifier := oauth2.GenerateVerifier()
 | 
			
		||||
 | 
			
		||||
	return &OAuth{
 | 
			
		||||
		Config:   config,
 | 
			
		||||
		Context:  ctx,
 | 
			
		||||
		Verifier: verifier,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (oauth *OAuth) GetAuthURL(state string) string {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,12 +11,6 @@ import (
 | 
			
		||||
	"golang.org/x/oauth2/endpoints"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewProviders(config types.OAuthConfig) *Providers {
 | 
			
		||||
	return &Providers{
 | 
			
		||||
		Config: config,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Providers struct {
 | 
			
		||||
	Config  types.OAuthConfig
 | 
			
		||||
	Github  *oauth.OAuth
 | 
			
		||||
@@ -24,60 +18,57 @@ type Providers struct {
 | 
			
		||||
	Generic *oauth.OAuth
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (providers *Providers) Init() {
 | 
			
		||||
func NewProviders(config types.OAuthConfig) *Providers {
 | 
			
		||||
	providers := &Providers{
 | 
			
		||||
		Config: config,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we have a client id and secret for github, initialize the oauth provider
 | 
			
		||||
	if providers.Config.GithubClientId != "" && providers.Config.GithubClientSecret != "" {
 | 
			
		||||
	if config.GithubClientId != "" && config.GithubClientSecret != "" {
 | 
			
		||||
		log.Info().Msg("Initializing Github OAuth")
 | 
			
		||||
 | 
			
		||||
		// Create a new oauth provider with the github config
 | 
			
		||||
		providers.Github = oauth.NewOAuth(oauth2.Config{
 | 
			
		||||
			ClientID:     providers.Config.GithubClientId,
 | 
			
		||||
			ClientSecret: providers.Config.GithubClientSecret,
 | 
			
		||||
			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/github", providers.Config.AppURL),
 | 
			
		||||
			ClientID:     config.GithubClientId,
 | 
			
		||||
			ClientSecret: config.GithubClientSecret,
 | 
			
		||||
			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/github", config.AppURL),
 | 
			
		||||
			Scopes:       GithubScopes(),
 | 
			
		||||
			Endpoint:     endpoints.GitHub,
 | 
			
		||||
		}, false)
 | 
			
		||||
 | 
			
		||||
		// Initialize the oauth provider
 | 
			
		||||
		providers.Github.Init()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we have a client id and secret for google, initialize the oauth provider
 | 
			
		||||
	if providers.Config.GoogleClientId != "" && providers.Config.GoogleClientSecret != "" {
 | 
			
		||||
	if config.GoogleClientId != "" && config.GoogleClientSecret != "" {
 | 
			
		||||
		log.Info().Msg("Initializing Google OAuth")
 | 
			
		||||
 | 
			
		||||
		// Create a new oauth provider with the google config
 | 
			
		||||
		providers.Google = oauth.NewOAuth(oauth2.Config{
 | 
			
		||||
			ClientID:     providers.Config.GoogleClientId,
 | 
			
		||||
			ClientSecret: providers.Config.GoogleClientSecret,
 | 
			
		||||
			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/google", providers.Config.AppURL),
 | 
			
		||||
			ClientID:     config.GoogleClientId,
 | 
			
		||||
			ClientSecret: config.GoogleClientSecret,
 | 
			
		||||
			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/google", config.AppURL),
 | 
			
		||||
			Scopes:       GoogleScopes(),
 | 
			
		||||
			Endpoint:     endpoints.Google,
 | 
			
		||||
		}, false)
 | 
			
		||||
 | 
			
		||||
		// Initialize the oauth provider
 | 
			
		||||
		providers.Google.Init()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we have a client id and secret for generic oauth, initialize the oauth provider
 | 
			
		||||
	if providers.Config.GenericClientId != "" && providers.Config.GenericClientSecret != "" {
 | 
			
		||||
	if config.GenericClientId != "" && config.GenericClientSecret != "" {
 | 
			
		||||
		log.Info().Msg("Initializing Generic OAuth")
 | 
			
		||||
 | 
			
		||||
		// Create a new oauth provider with the generic config
 | 
			
		||||
		providers.Generic = oauth.NewOAuth(oauth2.Config{
 | 
			
		||||
			ClientID:     providers.Config.GenericClientId,
 | 
			
		||||
			ClientSecret: providers.Config.GenericClientSecret,
 | 
			
		||||
			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/generic", providers.Config.AppURL),
 | 
			
		||||
			Scopes:       providers.Config.GenericScopes,
 | 
			
		||||
			ClientID:     config.GenericClientId,
 | 
			
		||||
			ClientSecret: config.GenericClientSecret,
 | 
			
		||||
			RedirectURL:  fmt.Sprintf("%s/api/oauth/callback/generic", config.AppURL),
 | 
			
		||||
			Scopes:       config.GenericScopes,
 | 
			
		||||
			Endpoint: oauth2.Endpoint{
 | 
			
		||||
				AuthURL:  providers.Config.GenericAuthURL,
 | 
			
		||||
				TokenURL: providers.Config.GenericTokenURL,
 | 
			
		||||
				AuthURL:  config.GenericAuthURL,
 | 
			
		||||
				TokenURL: config.GenericTokenURL,
 | 
			
		||||
			},
 | 
			
		||||
		}, providers.Config.GenericSkipSSL)
 | 
			
		||||
 | 
			
		||||
		// Initialize the oauth provider
 | 
			
		||||
		providers.Generic.Init()
 | 
			
		||||
		}, config.GenericSkipSSL)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return providers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (providers *Providers) GetProvider(provider string) *oauth.OAuth {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package api
 | 
			
		||||
package server
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
@@ -15,20 +15,13 @@ import (
 | 
			
		||||
	"github.com/rs/zerolog/log"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewAPI(config types.APIConfig, handlers *handlers.Handlers) *API {
 | 
			
		||||
	return &API{
 | 
			
		||||
		Config:   config,
 | 
			
		||||
		Handlers: handlers,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type API struct {
 | 
			
		||||
	Config   types.APIConfig
 | 
			
		||||
	Router   *gin.Engine
 | 
			
		||||
type Server struct {
 | 
			
		||||
	Config   types.ServerConfig
 | 
			
		||||
	Handlers *handlers.Handlers
 | 
			
		||||
	Router   *gin.Engine
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *API) Init() {
 | 
			
		||||
func NewServer(config types.ServerConfig, handlers *handlers.Handlers) (*Server, error) {
 | 
			
		||||
	// Disable gin logs
 | 
			
		||||
	gin.SetMode(gin.ReleaseMode)
 | 
			
		||||
 | 
			
		||||
@@ -42,7 +35,7 @@ func (api *API) Init() {
 | 
			
		||||
	dist, err := fs.Sub(assets.Assets, "dist")
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal().Err(err).Msg("Failed to get UI assets")
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Create file server
 | 
			
		||||
@@ -69,41 +62,38 @@ func (api *API) Init() {
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// Set router
 | 
			
		||||
	api.Router = router
 | 
			
		||||
	// Proxy routes
 | 
			
		||||
	router.GET("/api/auth/:proxy", handlers.AuthHandler)
 | 
			
		||||
 | 
			
		||||
	// Auth routes
 | 
			
		||||
	router.POST("/api/login", handlers.LoginHandler)
 | 
			
		||||
	router.POST("/api/totp", handlers.TotpHandler)
 | 
			
		||||
	router.POST("/api/logout", handlers.LogoutHandler)
 | 
			
		||||
 | 
			
		||||
	// Context routes
 | 
			
		||||
	router.GET("/api/app", handlers.AppHandler)
 | 
			
		||||
	router.GET("/api/user", handlers.UserHandler)
 | 
			
		||||
 | 
			
		||||
	// OAuth routes
 | 
			
		||||
	router.GET("/api/oauth/url/:provider", handlers.OauthUrlHandler)
 | 
			
		||||
	router.GET("/api/oauth/callback/:provider", handlers.OauthCallbackHandler)
 | 
			
		||||
 | 
			
		||||
	// App routes
 | 
			
		||||
	router.GET("/api/healthcheck", handlers.HealthcheckHandler)
 | 
			
		||||
 | 
			
		||||
	// Return the server
 | 
			
		||||
	return &Server{
 | 
			
		||||
		Config:   config,
 | 
			
		||||
		Handlers: handlers,
 | 
			
		||||
		Router:   router,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *API) SetupRoutes() {
 | 
			
		||||
	// Proxy
 | 
			
		||||
	api.Router.GET("/api/auth/:proxy", api.Handlers.AuthHandler)
 | 
			
		||||
 | 
			
		||||
	// Auth
 | 
			
		||||
	api.Router.POST("/api/login", api.Handlers.LoginHandler)
 | 
			
		||||
	api.Router.POST("/api/totp", api.Handlers.TotpHandler)
 | 
			
		||||
	api.Router.POST("/api/logout", api.Handlers.LogoutHandler)
 | 
			
		||||
 | 
			
		||||
	// Context
 | 
			
		||||
	api.Router.GET("/api/app", api.Handlers.AppHandler)
 | 
			
		||||
	api.Router.GET("/api/user", api.Handlers.UserHandler)
 | 
			
		||||
 | 
			
		||||
	// OAuth
 | 
			
		||||
	api.Router.GET("/api/oauth/url/:provider", api.Handlers.OauthUrlHandler)
 | 
			
		||||
	api.Router.GET("/api/oauth/callback/:provider", api.Handlers.OauthCallbackHandler)
 | 
			
		||||
 | 
			
		||||
	// App
 | 
			
		||||
	api.Router.GET("/api/healthcheck", api.Handlers.HealthcheckHandler)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (api *API) Run() {
 | 
			
		||||
	log.Info().Str("address", api.Config.Address).Int("port", api.Config.Port).Msg("Starting server")
 | 
			
		||||
 | 
			
		||||
func (s *Server) Start() error {
 | 
			
		||||
	// Run server
 | 
			
		||||
	err := api.Router.Run(fmt.Sprintf("%s:%d", api.Config.Address, api.Config.Port))
 | 
			
		||||
	log.Info().Str("address", s.Config.Address).Int("port", s.Config.Port).Msg("Starting server")
 | 
			
		||||
 | 
			
		||||
	// Check for errors
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal().Err(err).Msg("Failed to start server")
 | 
			
		||||
	}
 | 
			
		||||
	return s.Router.Run(fmt.Sprintf("%s:%d", s.Config.Address, s.Config.Port))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// zerolog is a middleware for gin that logs requests using zerolog
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
package api_test
 | 
			
		||||
package server_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
@@ -8,19 +8,19 @@ import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"tinyauth/internal/api"
 | 
			
		||||
	"tinyauth/internal/auth"
 | 
			
		||||
	"tinyauth/internal/docker"
 | 
			
		||||
	"tinyauth/internal/handlers"
 | 
			
		||||
	"tinyauth/internal/hooks"
 | 
			
		||||
	"tinyauth/internal/providers"
 | 
			
		||||
	"tinyauth/internal/server"
 | 
			
		||||
	"tinyauth/internal/types"
 | 
			
		||||
 | 
			
		||||
	"github.com/magiconair/properties/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Simple API config for tests
 | 
			
		||||
var apiConfig = types.APIConfig{
 | 
			
		||||
// Simple server config for tests
 | 
			
		||||
var serverConfig = types.ServerConfig{
 | 
			
		||||
	Port:    8080,
 | 
			
		||||
	Address: "0.0.0.0",
 | 
			
		||||
}
 | 
			
		||||
@@ -68,15 +68,11 @@ var user = types.User{
 | 
			
		||||
	Password: "$2a$10$AvGHLTYv3xiRJ0xV9xs3XeVIlkGTygI9nqIamFYB5Xu.5.0UWF7B6", // pass
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// We need all this to be able to test the API
 | 
			
		||||
func getAPI(t *testing.T) *api.API {
 | 
			
		||||
// We need all this to be able to test the server
 | 
			
		||||
func getServer(t *testing.T) *server.Server {
 | 
			
		||||
	// Create docker service
 | 
			
		||||
	docker := docker.NewDocker()
 | 
			
		||||
	docker, err := docker.NewDocker()
 | 
			
		||||
 | 
			
		||||
	// Initialize docker
 | 
			
		||||
	err := docker.Init()
 | 
			
		||||
 | 
			
		||||
	// Check if there was an error
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to initialize docker: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -93,31 +89,29 @@ func getAPI(t *testing.T) *api.API {
 | 
			
		||||
	// Create providers service
 | 
			
		||||
	providers := providers.NewProviders(types.OAuthConfig{})
 | 
			
		||||
 | 
			
		||||
	// Initialize providers
 | 
			
		||||
	providers.Init()
 | 
			
		||||
 | 
			
		||||
	// Create hooks service
 | 
			
		||||
	hooks := hooks.NewHooks(hooksConfig, auth, providers)
 | 
			
		||||
 | 
			
		||||
	// Create handlers service
 | 
			
		||||
	handlers := handlers.NewHandlers(handlersConfig, auth, hooks, providers, docker)
 | 
			
		||||
 | 
			
		||||
	// Create API
 | 
			
		||||
	api := api.NewAPI(apiConfig, handlers)
 | 
			
		||||
	// Create server
 | 
			
		||||
	srv, err := server.NewServer(serverConfig, handlers)
 | 
			
		||||
 | 
			
		||||
	// Setup routes
 | 
			
		||||
	api.Init()
 | 
			
		||||
	api.SetupRoutes()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Failed to create server: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return api
 | 
			
		||||
	// Return the server
 | 
			
		||||
	return srv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test login (we will need this for the other tests)
 | 
			
		||||
// Test login
 | 
			
		||||
func TestLogin(t *testing.T) {
 | 
			
		||||
	t.Log("Testing login")
 | 
			
		||||
 | 
			
		||||
	// Get API
 | 
			
		||||
	api := getAPI(t)
 | 
			
		||||
	// Get server
 | 
			
		||||
	api := getServer(t)
 | 
			
		||||
 | 
			
		||||
	// Create recorder
 | 
			
		||||
	recorder := httptest.NewRecorder()
 | 
			
		||||
@@ -162,8 +156,8 @@ func TestLogin(t *testing.T) {
 | 
			
		||||
func TestAppContext(t *testing.T) {
 | 
			
		||||
	t.Log("Testing app context")
 | 
			
		||||
 | 
			
		||||
	// Get API
 | 
			
		||||
	api := getAPI(t)
 | 
			
		||||
	// Get server
 | 
			
		||||
	api := getServer(t)
 | 
			
		||||
 | 
			
		||||
	// Create recorder
 | 
			
		||||
	recorder := httptest.NewRecorder()
 | 
			
		||||
@@ -230,8 +224,8 @@ func TestAppContext(t *testing.T) {
 | 
			
		||||
func TestUserContext(t *testing.T) {
 | 
			
		||||
	t.Log("Testing user context")
 | 
			
		||||
 | 
			
		||||
	// Get API
 | 
			
		||||
	api := getAPI(t)
 | 
			
		||||
	// Get server
 | 
			
		||||
	api := getServer(t)
 | 
			
		||||
 | 
			
		||||
	// Create recorder
 | 
			
		||||
	recorder := httptest.NewRecorder()
 | 
			
		||||
@@ -288,8 +282,8 @@ func TestUserContext(t *testing.T) {
 | 
			
		||||
func TestLogout(t *testing.T) {
 | 
			
		||||
	t.Log("Testing logout")
 | 
			
		||||
 | 
			
		||||
	// Get API
 | 
			
		||||
	api := getAPI(t)
 | 
			
		||||
	// Get server
 | 
			
		||||
	api := getServer(t)
 | 
			
		||||
 | 
			
		||||
	// Create recorder
 | 
			
		||||
	recorder := httptest.NewRecorder()
 | 
			
		||||
@@ -319,5 +313,3 @@ func TestLogout(t *testing.T) {
 | 
			
		||||
		t.Fatalf("Cookie not flushed")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: Testing for the oauth stuff
 | 
			
		||||
@@ -69,8 +69,8 @@ type OAuthConfig struct {
 | 
			
		||||
	AppURL              string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// APIConfig is the configuration for the API
 | 
			
		||||
type APIConfig struct {
 | 
			
		||||
// ServerConfig is the configuration for the server
 | 
			
		||||
type ServerConfig struct {
 | 
			
		||||
	Port    int
 | 
			
		||||
	Address string
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user