mirror of
				https://github.com/steveiliop56/tinyauth.git
				synced 2025-10-30 21:55:43 +00:00 
			
		
		
		
	feat: make app configurable
This commit is contained in:
		
							
								
								
									
										58
									
								
								cmd/root.go
									
									
									
									
									
								
							
							
						
						
									
										58
									
								
								cmd/root.go
									
									
									
									
									
								
							| @@ -2,17 +2,47 @@ package cmd | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"os" | 	"os" | ||||||
|  | 	"time" | ||||||
| 	"tinyauth/internal/api" | 	"tinyauth/internal/api" | ||||||
|  | 	"tinyauth/internal/types" | ||||||
|  | 	"tinyauth/internal/utils" | ||||||
|  |  | ||||||
|  | 	"github.com/go-playground/validator/v10" | ||||||
|  | 	"github.com/rs/zerolog" | ||||||
|  | 	"github.com/rs/zerolog/log" | ||||||
| 	"github.com/spf13/cobra" | 	"github.com/spf13/cobra" | ||||||
|  | 	"github.com/spf13/viper" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var rootCmd = &cobra.Command{ | var rootCmd = &cobra.Command{ | ||||||
| 	Use:   "tinyauth", | 	Use:   "tinyauth", | ||||||
| 	Short: "A dead simple login page for your apps.", | 	Short: "An extremely simple traefik forward auth proxy.", | ||||||
| 	Long: `Tinyauth is an extremely simple traefik forward-auth login screen that makes securing your apps easy.`, | 	Long: `Tinyauth is an extremely simple traefik forward-auth login screen that makes securing your apps easy.`, | ||||||
| 	Run: func(cmd *cobra.Command, args []string) { | 	Run: func(cmd *cobra.Command, args []string) { | ||||||
| 		api.Run() | 		// Logger | ||||||
|  | 		log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Timestamp().Logger() | ||||||
|  | 		log.Info().Msg("Starting tinyauth") | ||||||
|  |  | ||||||
|  | 		// Get config | ||||||
|  | 		log.Info().Msg("Parsing config") | ||||||
|  | 		var config types.Config | ||||||
|  | 		parseErr := viper.Unmarshal(&config) | ||||||
|  | 		HandleError(parseErr, "Failed to parse config") | ||||||
|  |  | ||||||
|  | 		// Validate config | ||||||
|  | 		log.Info().Msg("Validating config") | ||||||
|  | 		validator := validator.New() | ||||||
|  | 		validateErr := validator.Struct(config) | ||||||
|  | 		HandleError(validateErr, "Invalid config") | ||||||
|  |  | ||||||
|  | 		// Create users list | ||||||
|  | 		log.Info().Msg("Creating users list") | ||||||
|  | 		userList, createErr := utils.CreateUsersList(config.Users) | ||||||
|  | 		HandleError(createErr, "Failed to create users list") | ||||||
|  |  | ||||||
|  | 		// Start server | ||||||
|  | 		log.Info().Msg("Starting server") | ||||||
|  | 		api.Run(config, userList) | ||||||
| 	}, | 	}, | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -22,3 +52,27 @@ func Execute() { | |||||||
| 		os.Exit(1) | 		os.Exit(1) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func HandleError(err error, msg string) { | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatal().Err(err).Msg(msg) | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	viper.AutomaticEnv() | ||||||
|  | 	rootCmd.Flags().IntP("port", "p", 8080, "Port to run the server on.") | ||||||
|  | 	rootCmd.Flags().String("address", "0.0.0.0", "Address to bind the server to.") | ||||||
|  | 	rootCmd.Flags().String("secret", "", "Secret to use for the cookie.") | ||||||
|  | 	rootCmd.Flags().String("root-url", "", "Root URL of traefik.") | ||||||
|  | 	rootCmd.Flags().String("app-url", "", "The tinyauth URL.") | ||||||
|  | 	rootCmd.Flags().String("users", "", "Comma separated list of users in the format username:bcrypt-hashed-password.") | ||||||
|  | 	viper.BindEnv("port", "PORT") | ||||||
|  | 	viper.BindEnv("address", "ADDRESS") | ||||||
|  | 	viper.BindEnv("secret", "SECRET") | ||||||
|  | 	viper.BindEnv("root-url", "ROOT_URL") | ||||||
|  | 	viper.BindEnv("app-url", "APP_URL") | ||||||
|  | 	viper.BindEnv("users", "USERS") | ||||||
|  | 	viper.BindPFlags(rootCmd.Flags()) | ||||||
|  | } | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ services: | |||||||
|     volumes: |     volumes: | ||||||
|       - /var/run/docker.sock:/var/run/docker.sock |       - /var/run/docker.sock:/var/run/docker.sock | ||||||
|     labels: |     labels: | ||||||
|       traefik.http.middlewares.basic-auth.basicauth.users: user:$$2y$$05$$HgkRucUeFKgZ7ZsPkIJY6uAX2Nh8ZAeIlJ5Rpq.05yYBPsITTnnLu |  | ||||||
|       traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth |       traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth | ||||||
|  |  | ||||||
|   nginx: |   nginx: | ||||||
| @@ -30,6 +29,13 @@ services: | |||||||
|       dockerfile: Dockerfile |       dockerfile: Dockerfile | ||||||
|     ports: |     ports: | ||||||
|       - 3000:3000 |       - 3000:3000 | ||||||
|  |     environment: | ||||||
|  |       - PORT=3000 | ||||||
|  |       - ADDRESS=0.0.0.0 | ||||||
|  |       - SECRET=ghDaPuDFjvlBuF93zcacFrDiHFHTZhUh | ||||||
|  |       - ROOT_URL=http://dev.local | ||||||
|  |       - APP_URL=http://tinyauth.dev.local | ||||||
|  |       - USERS=user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u | ||||||
|     labels: |     labels: | ||||||
|       traefik.enable: true |       traefik.enable: true | ||||||
|       traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.local`) |       traefik.http.routers.tinyauth.rule: Host(`tinyauth.dev.local`) | ||||||
|   | |||||||
							
								
								
									
										17
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								go.mod
									
									
									
									
									
								
							| @@ -11,6 +11,7 @@ require ( | |||||||
| 	github.com/bytedance/sonic v1.12.7 // indirect | 	github.com/bytedance/sonic v1.12.7 // indirect | ||||||
| 	github.com/bytedance/sonic/loader v0.2.3 // indirect | 	github.com/bytedance/sonic/loader v0.2.3 // indirect | ||||||
| 	github.com/cloudwego/base64x v0.1.4 // indirect | 	github.com/cloudwego/base64x v0.1.4 // indirect | ||||||
|  | 	github.com/fsnotify/fsnotify v1.7.0 // indirect | ||||||
| 	github.com/gabriel-vasile/mimetype v1.4.8 // indirect | 	github.com/gabriel-vasile/mimetype v1.4.8 // indirect | ||||||
| 	github.com/gin-contrib/sessions v1.0.2 // indirect | 	github.com/gin-contrib/sessions v1.0.2 // indirect | ||||||
| 	github.com/gin-contrib/sse v1.0.0 // indirect | 	github.com/gin-contrib/sse v1.0.0 // indirect | ||||||
| @@ -22,22 +23,38 @@ require ( | |||||||
| 	github.com/gorilla/context v1.1.2 // indirect | 	github.com/gorilla/context v1.1.2 // indirect | ||||||
| 	github.com/gorilla/securecookie v1.1.2 // indirect | 	github.com/gorilla/securecookie v1.1.2 // indirect | ||||||
| 	github.com/gorilla/sessions v1.2.2 // indirect | 	github.com/gorilla/sessions v1.2.2 // indirect | ||||||
|  | 	github.com/hashicorp/hcl v1.0.0 // indirect | ||||||
| 	github.com/inconshreveable/mousetrap v1.1.0 // indirect | 	github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||||||
| 	github.com/json-iterator/go v1.1.12 // indirect | 	github.com/json-iterator/go v1.1.12 // indirect | ||||||
| 	github.com/klauspost/cpuid/v2 v2.2.9 // indirect | 	github.com/klauspost/cpuid/v2 v2.2.9 // indirect | ||||||
| 	github.com/leodido/go-urn v1.4.0 // indirect | 	github.com/leodido/go-urn v1.4.0 // indirect | ||||||
|  | 	github.com/magiconair/properties v1.8.7 // indirect | ||||||
|  | 	github.com/mattn/go-colorable v0.1.14 // indirect | ||||||
| 	github.com/mattn/go-isatty v0.0.20 // indirect | 	github.com/mattn/go-isatty v0.0.20 // indirect | ||||||
|  | 	github.com/mitchellh/mapstructure v1.5.0 // indirect | ||||||
| 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||||||
| 	github.com/modern-go/reflect2 v1.0.2 // indirect | 	github.com/modern-go/reflect2 v1.0.2 // indirect | ||||||
| 	github.com/pelletier/go-toml/v2 v2.2.3 // indirect | 	github.com/pelletier/go-toml/v2 v2.2.3 // indirect | ||||||
|  | 	github.com/rs/zerolog v1.33.0 // indirect | ||||||
|  | 	github.com/sagikazarmark/locafero v0.4.0 // indirect | ||||||
|  | 	github.com/sagikazarmark/slog-shim v0.1.0 // indirect | ||||||
|  | 	github.com/sourcegraph/conc v0.3.0 // indirect | ||||||
|  | 	github.com/spf13/afero v1.11.0 // indirect | ||||||
|  | 	github.com/spf13/cast v1.6.0 // indirect | ||||||
| 	github.com/spf13/pflag v1.0.5 // indirect | 	github.com/spf13/pflag v1.0.5 // indirect | ||||||
|  | 	github.com/spf13/viper v1.19.0 // indirect | ||||||
|  | 	github.com/subosito/gotenv v1.6.0 // indirect | ||||||
| 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | ||||||
| 	github.com/ugorji/go/codec v1.2.12 // indirect | 	github.com/ugorji/go/codec v1.2.12 // indirect | ||||||
|  | 	go.uber.org/atomic v1.9.0 // indirect | ||||||
|  | 	go.uber.org/multierr v1.9.0 // indirect | ||||||
| 	golang.org/x/arch v0.13.0 // indirect | 	golang.org/x/arch v0.13.0 // indirect | ||||||
| 	golang.org/x/crypto v0.32.0 // indirect | 	golang.org/x/crypto v0.32.0 // indirect | ||||||
|  | 	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect | ||||||
| 	golang.org/x/net v0.34.0 // indirect | 	golang.org/x/net v0.34.0 // indirect | ||||||
| 	golang.org/x/sys v0.29.0 // indirect | 	golang.org/x/sys v0.29.0 // indirect | ||||||
| 	golang.org/x/text v0.21.0 // indirect | 	golang.org/x/text v0.21.0 // indirect | ||||||
| 	google.golang.org/protobuf v1.36.3 // indirect | 	google.golang.org/protobuf v1.36.3 // indirect | ||||||
|  | 	gopkg.in/ini.v1 v1.67.0 // indirect | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								go.sum
									
									
									
									
									
								
							| @@ -6,10 +6,13 @@ github.com/bytedance/sonic/loader v0.2.3/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFos | |||||||
| github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= | github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= | ||||||
| github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= | github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= | ||||||
| github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= | github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= | ||||||
|  | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= | ||||||
| github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= | github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= | ||||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||||
|  | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= | ||||||
|  | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= | ||||||
| github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= | github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= | ||||||
| github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= | github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= | ||||||
| github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA= | github.com/gin-contrib/sessions v1.0.2 h1:UaIjUvTH1cMeOdj3in6dl+Xb6It8RiKRF9Z1anbUyCA= | ||||||
| @@ -28,6 +31,7 @@ github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE | |||||||
| github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= | github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus= | ||||||
| github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= | github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= | ||||||
| github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= | github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= | ||||||
|  | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | ||||||
| github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= | ||||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| @@ -40,6 +44,8 @@ github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kX | |||||||
| github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= | github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= | ||||||
| github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= | github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= | ||||||
| github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= | github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= | ||||||
|  | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= | ||||||
|  | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= | ||||||
| github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= | ||||||
| github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= | ||||||
| github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | ||||||
| @@ -50,8 +56,17 @@ github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK | |||||||
| github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= | ||||||
| github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= | ||||||
| github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= | ||||||
|  | github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= | ||||||
|  | github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= | ||||||
|  | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= | ||||||
|  | github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= | ||||||
|  | github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= | ||||||
|  | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | ||||||
|  | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||||||
| github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= | ||||||
| github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= | ||||||
|  | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= | ||||||
|  | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= | ||||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= | ||||||
| github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||||
| @@ -59,13 +74,29 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G | |||||||
| github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | ||||||
| github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= | github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= | ||||||
| github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= | github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= | ||||||
|  | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
|  | github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= | ||||||
|  | github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= | ||||||
|  | github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= | ||||||
| github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||||||
|  | github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= | ||||||
|  | github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= | ||||||
|  | github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= | ||||||
|  | github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= | ||||||
|  | github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= | ||||||
|  | github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= | ||||||
|  | github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= | ||||||
|  | github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= | ||||||
|  | github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= | ||||||
|  | github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= | ||||||
| github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= | github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= | ||||||
| github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= | github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= | ||||||
| github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||||||
| github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||||||
|  | github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= | ||||||
|  | github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= | ||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||||||
| github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||||
| @@ -78,17 +109,27 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o | |||||||
| github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||||||
| github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||||
| github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||||
|  | github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= | ||||||
|  | github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= | ||||||
| github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= | github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= | ||||||
| github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= | ||||||
| github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= | github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= | ||||||
| github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= | ||||||
|  | go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= | ||||||
|  | go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= | ||||||
|  | go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= | ||||||
|  | go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= | ||||||
| golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA= | golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA= | ||||||
| golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= | ||||||
| golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= | golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= | ||||||
| golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= | golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= | ||||||
|  | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= | ||||||
|  | golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= | ||||||
| golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= | ||||||
| golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= | ||||||
|  | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= | golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= | ||||||
| golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
| golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= | ||||||
| @@ -99,6 +140,8 @@ google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1B | |||||||
| google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
|  | gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= | ||||||
|  | gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= | ||||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
|   | |||||||
| @@ -6,22 +6,36 @@ import ( | |||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"os" | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 	"time" | ||||||
| 	"tinyauth/internal/assets" | 	"tinyauth/internal/assets" | ||||||
|  | 	"tinyauth/internal/auth" | ||||||
| 	"tinyauth/internal/types" | 	"tinyauth/internal/types" | ||||||
|  |  | ||||||
| 	"github.com/gin-contrib/sessions" | 	"github.com/gin-contrib/sessions" | ||||||
| 	"github.com/gin-contrib/sessions/cookie" | 	"github.com/gin-contrib/sessions/cookie" | ||||||
| 	"github.com/gin-gonic/gin" | 	"github.com/gin-gonic/gin" | ||||||
| 	"github.com/google/go-querystring/query" | 	"github.com/google/go-querystring/query" | ||||||
|  | 	"github.com/rs/zerolog/log" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func Run() { | func Run(config types.Config, users types.UserList) { | ||||||
| 	router := gin.Default() | 	gin.SetMode(gin.ReleaseMode) | ||||||
| 	dist, _ := fs.Sub(assets.Assets, "dist") | 	router := gin.New() | ||||||
|  | 	router.Use(zerolog()) | ||||||
|  | 	dist, distErr := fs.Sub(assets.Assets, "dist") | ||||||
|  |  | ||||||
|  | 	if distErr != nil { | ||||||
|  | 		log.Fatal().Err(distErr).Msg("Failed to get UI assets") | ||||||
|  | 		os.Exit(1) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	fileServer := http.FileServer(http.FS(dist)) | 	fileServer := http.FileServer(http.FS(dist)) | ||||||
| 	store := cookie.NewStore([]byte("secret")) | 	store := cookie.NewStore([]byte(config.Secret)) | ||||||
|  |  | ||||||
|  | 	domain := strings.Split(config.RootURL, "://")[1] | ||||||
|  |  | ||||||
| 	store.Options(sessions.Options{ | 	store.Options(sessions.Options{ | ||||||
| 		Domain: ".dev.local", | 		Domain: fmt.Sprintf(".%s", domain), | ||||||
| 		Path: "/", | 		Path: "/", | ||||||
| 	}) | 	}) | ||||||
|   	router.Use(sessions.Sessions("tinyauth", store)) |   	router.Use(sessions.Sessions("tinyauth", store)) | ||||||
| @@ -41,21 +55,35 @@ func Run() { | |||||||
| 		session := sessions.Default(c) | 		session := sessions.Default(c) | ||||||
| 		value := session.Get("tinyauth") | 		value := session.Get("tinyauth") | ||||||
|  |  | ||||||
| 		if value == nil || value != "true" { | 		if value != nil { | ||||||
| 			uri := c.Request.Header.Get("X-Forwarded-Uri") | 			usernameString, ok := value.(string) | ||||||
| 			proto := c.Request.Header.Get("X-Forwarded-Proto") | 			if ok { | ||||||
| 			host := c.Request.Header.Get("X-Forwarded-Host") | 				if auth.FindUser(users, usernameString) != nil { | ||||||
| 			queries := types.LoginQuery{ |  | ||||||
| 				RedirectURI: fmt.Sprintf("%s://%s%s", proto, host, uri), |  | ||||||
| 			} |  | ||||||
| 			values, _ := query.Values(queries) |  | ||||||
| 			c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("http://tinyauth.dev.local?%s", values.Encode())) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 					c.JSON(200, gin.H{ | 					c.JSON(200, gin.H{ | ||||||
| 						"status": 200, | 						"status": 200, | ||||||
| 						"message": "Authorized", | 						"message": "Authorized", | ||||||
| 					}) | 					}) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		uri := c.Request.Header.Get("X-Forwarded-Uri") | ||||||
|  | 		proto := c.Request.Header.Get("X-Forwarded-Proto") | ||||||
|  | 		host := c.Request.Header.Get("X-Forwarded-Host") | ||||||
|  | 		queries, queryErr := query.Values(types.LoginQuery{ | ||||||
|  | 			RedirectURI: fmt.Sprintf("%s://%s%s", proto, host, uri), | ||||||
|  | 		}) | ||||||
|  |  | ||||||
|  | 		if queryErr != nil { | ||||||
|  | 			c.JSON(501, gin.H{ | ||||||
|  | 				"status": 501, | ||||||
|  | 				"message": "Internal Server Error", | ||||||
|  | 			}) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		c.Redirect(http.StatusTemporaryRedirect, fmt.Sprintf("%s/?%s", config.AppURL, queries.Encode())) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	router.POST("/api/login", func (c *gin.Context) { | 	router.POST("/api/login", func (c *gin.Context) { | ||||||
| @@ -71,7 +99,17 @@ func Run() { | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if login.Email != "user@example.com" || login.Password != "password" { | 		user := auth.FindUser(users, login.Username) | ||||||
|  |  | ||||||
|  | 		if user == nil { | ||||||
|  | 			c.JSON(401, gin.H{ | ||||||
|  | 				"status": 401, | ||||||
|  | 				"message": "Unauthorized", | ||||||
|  | 			}) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if !auth.CheckPassword(*user, login.Password) { | ||||||
| 			c.JSON(401, gin.H{ | 			c.JSON(401, gin.H{ | ||||||
| 				"status": 401, | 				"status": 401, | ||||||
| 				"message": "Unauthorized", | 				"message": "Unauthorized", | ||||||
| @@ -80,7 +118,7 @@ func Run() { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		session := sessions.Default(c) | 		session := sessions.Default(c) | ||||||
| 		session.Set("tinyauth", "true") | 		session.Set("tinyauth", user.Username) | ||||||
| 		session.Save() | 		session.Save() | ||||||
|  |  | ||||||
| 		c.JSON(200, gin.H{ | 		c.JSON(200, gin.H{ | ||||||
| @@ -104,19 +142,50 @@ func Run() { | |||||||
| 		session := sessions.Default(c) | 		session := sessions.Default(c) | ||||||
| 		value := session.Get("tinyauth") | 		value := session.Get("tinyauth") | ||||||
|  |  | ||||||
| 		if value == nil || value != "true" { | 		if value != nil { | ||||||
| 			c.JSON(200, gin.H{ | 			usernameString, ok := value.(string) | ||||||
| 				"status": 200, | 			if ok { | ||||||
| 				"isLoggedIn": false, | 				if auth.FindUser(users, usernameString) != nil { | ||||||
| 			}) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 					c.JSON(200, gin.H{ | 					c.JSON(200, gin.H{ | ||||||
| 						"status": 200, | 						"status": 200, | ||||||
| 						"isLoggedIn": true, | 						"isLoggedIn": true, | ||||||
|  | 						"username": usernameString, | ||||||
|  | 					}) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		c.JSON(200, gin.H{ | ||||||
|  | 			"status": 200, | ||||||
|  | 			"isLoggedIn": false, | ||||||
|  | 			"username": "", | ||||||
| 		}) | 		}) | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	router.Run(":3000") | 	router.Run(fmt.Sprintf("%s:%d", config.Address, config.Port)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func zerolog() gin.HandlerFunc { | ||||||
|  | 	return func(c *gin.Context) { | ||||||
|  | 		tStart := time.Now() | ||||||
|  |  | ||||||
|  | 		c.Next() | ||||||
|  |  | ||||||
|  | 		code := c.Writer.Status() | ||||||
|  | 		address := c.Request.RemoteAddr | ||||||
|  | 		method := c.Request.Method | ||||||
|  | 		path := c.Request.URL.Path | ||||||
|  | 		 | ||||||
|  | 		latency := time.Since(tStart).String() | ||||||
|  |  | ||||||
|  | 		switch { | ||||||
|  | 			case code >= 200 && code < 300: | ||||||
|  | 				log.Info().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request") | ||||||
|  | 			case code >= 300 && code < 400: | ||||||
|  | 				log.Warn().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request") | ||||||
|  | 			case code >= 400: | ||||||
|  | 				log.Error().Str("method", method).Str("path", path).Str("address", address).Int("status", code).Str("latency", latency).Msg("Request") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
							
								
								
									
										21
									
								
								internal/auth/auth.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								internal/auth/auth.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | package auth | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"tinyauth/internal/types" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/crypto/bcrypt" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func FindUser(userList types.UserList, username string) (*types.User) { | ||||||
|  | 	for _, user := range userList.Users { | ||||||
|  | 		if user.Username == username { | ||||||
|  | 			return &user | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func CheckPassword(user types.User, password string) bool { | ||||||
|  | 	hashedPasswordErr := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) | ||||||
|  | 	return hashedPasswordErr == nil | ||||||
|  | } | ||||||
| @@ -5,6 +5,24 @@ type LoginQuery struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type LoginRequest struct { | type LoginRequest struct { | ||||||
| 	Email string `json:"email"` | 	Username string `json:"username"` | ||||||
| 	Password string `json:"password"` | 	Password string `json:"password"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type User struct { | ||||||
|  | 	Username string | ||||||
|  | 	Password string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type UserList struct { | ||||||
|  | 	Users []User | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type Config struct { | ||||||
|  | 	Port int `validate:"number" mapstructure:"port"` | ||||||
|  | 	Address string `mapstructure:"address, ip4_addr"` | ||||||
|  | 	Secret string `validate:"required,len=32" mapstructure:"secret"` | ||||||
|  | 	RootURL string `validate:"required,url" mapstructure:"root-url"` | ||||||
|  | 	AppURL string `validate:"required,url" mapstructure:"app-url"` | ||||||
|  | 	Users string `validate:"required" mapstructure:"users"` | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								internal/utils/utils.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								internal/utils/utils.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | package utils | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 	"strings" | ||||||
|  | 	"tinyauth/internal/types" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func CreateUsersList(users string) (types.UserList, error) { | ||||||
|  | 	var userList types.UserList | ||||||
|  | 	userListString := strings.Split(users, ",") | ||||||
|  |  | ||||||
|  | 	if len(userListString) == 0 { | ||||||
|  | 		return types.UserList{}, errors.New("no users found") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for _, user := range userListString { | ||||||
|  | 		userSplit := strings.Split(user, ":") | ||||||
|  | 		if len(userSplit) != 2 { | ||||||
|  | 			return types.UserList{}, errors.New("invalid user format") | ||||||
|  | 		} | ||||||
|  | 		userList.Users = append(userList.Users, types.User{ | ||||||
|  | 			Username: userSplit[0], | ||||||
|  | 			Password: userSplit[1], | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return userList, nil | ||||||
|  | } | ||||||
| @@ -20,7 +20,7 @@ export const LoginPage = () => { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   const schema = z.object({ |   const schema = z.object({ | ||||||
|     email: z.string().email({ message: "Invalid email" }), |     username: z.string(), | ||||||
|     password: z.string(), |     password: z.string(), | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -29,7 +29,7 @@ export const LoginPage = () => { | |||||||
|   const form = useForm({ |   const form = useForm({ | ||||||
|     mode: "uncontrolled", |     mode: "uncontrolled", | ||||||
|     initialValues: { |     initialValues: { | ||||||
|       email: "", |       username: "", | ||||||
|       password: "", |       password: "", | ||||||
|     }, |     }, | ||||||
|     validate: zodResolver(schema), |     validate: zodResolver(schema), | ||||||
| @@ -42,7 +42,7 @@ export const LoginPage = () => { | |||||||
|     onError: () => { |     onError: () => { | ||||||
|       notifications.show({ |       notifications.show({ | ||||||
|         title: "Failed to login", |         title: "Failed to login", | ||||||
|         message: "Check your email and password", |         message: "Check your username and password", | ||||||
|         color: "red", |         color: "red", | ||||||
|       }); |       }); | ||||||
|     }, |     }, | ||||||
| @@ -68,12 +68,12 @@ export const LoginPage = () => { | |||||||
|       <Paper shadow="md" p={30} mt={30} radius="md" withBorder> |       <Paper shadow="md" p={30} mt={30} radius="md" withBorder> | ||||||
|         <form onSubmit={form.onSubmit(handleSubmit)}> |         <form onSubmit={form.onSubmit(handleSubmit)}> | ||||||
|           <TextInput |           <TextInput | ||||||
|             label="Email" |             label="Username" | ||||||
|             placeholder="you@example.com" |             placeholder="tinyauth" | ||||||
|             required |             required | ||||||
|             disabled={loginMutation.isLoading} |             disabled={loginMutation.isLoading} | ||||||
|             key={form.key("email")} |             key={form.key("username")} | ||||||
|             {...form.getInputProps("email")} |             {...form.getInputProps("username")} | ||||||
|           /> |           /> | ||||||
|           <PasswordInput |           <PasswordInput | ||||||
|             label="Password" |             label="Password" | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ import { Navigate } from "react-router"; | |||||||
| import { Layout } from "../components/layouts/layout"; | import { Layout } from "../components/layouts/layout"; | ||||||
|  |  | ||||||
| export const LogoutPage = () => { | export const LogoutPage = () => { | ||||||
|   const { isLoggedIn } = useUserContext(); |   const { isLoggedIn, username } = useUserContext(); | ||||||
|  |  | ||||||
|   if (!isLoggedIn) { |   if (!isLoggedIn) { | ||||||
|     return <Navigate to="/login" />; |     return <Navigate to="/login" />; | ||||||
| @@ -43,7 +43,8 @@ export const LogoutPage = () => { | |||||||
|           Logout |           Logout | ||||||
|         </Text> |         </Text> | ||||||
|         <Text> |         <Text> | ||||||
|           You are already logged in, click the button below to log out. |           You are currently logged in as {username}, click the button below to | ||||||
|  |           log out. | ||||||
|         </Text> |         </Text> | ||||||
|         <Button |         <Button | ||||||
|           fullWidth |           fullWidth | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import { z } from "zod"; | |||||||
|  |  | ||||||
| export const userContextSchema = z.object({ | export const userContextSchema = z.object({ | ||||||
|   isLoggedIn: z.boolean(), |   isLoggedIn: z.boolean(), | ||||||
|  |   username: z.string(), | ||||||
| }); | }); | ||||||
|  |  | ||||||
| export type UserContextSchemaType = z.infer<typeof userContextSchema>; | export type UserContextSchemaType = z.infer<typeof userContextSchema>; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stavros
					Stavros