From 8b8e2ca918759e8bf0f14d8ddc8b26a7684e12ce Mon Sep 17 00:00:00 2001 From: Stephanie Gredell Date: Sat, 2 Nov 2024 19:35:30 -0700 Subject: [PATCH] organize routes and add a pages package where the handlers will go for that route --- .gitignore | 3 +- auth/auth.go | 60 +++++++++++++++++++++++++++++++++ go.mod | 5 +++ go.sum | 12 +++++++ main.go | 91 ++++++++++++-------------------------------------- pages/home.go | 41 +++++++++++++++++++++++ pages/login.go | 12 +++++++ 7 files changed, 153 insertions(+), 71 deletions(-) create mode 100644 auth/auth.go create mode 100644 pages/home.go create mode 100644 pages/login.go diff --git a/.gitignore b/.gitignore index 972b726..52cd6d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea -todo.md \ No newline at end of file +todo.md +.env \ No newline at end of file diff --git a/auth/auth.go b/auth/auth.go new file mode 100644 index 0000000..4d0aca9 --- /dev/null +++ b/auth/auth.go @@ -0,0 +1,60 @@ +package auth + +import ( + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/markbates/goth" + "github.com/markbates/goth/gothic" + "log" + "net/http" +) + +func Login(c *gin.Context) { + providerName := c.Param("provider") + + // Begin the authentication process + provider, err := goth.GetProvider(providerName) + if err != nil { + c.String(http.StatusInternalServerError, "Error getting provider: %s", err) + return + } + + state := uuid.New().String() + + session, err := provider.BeginAuth(state) + if err != nil { + c.String(http.StatusInternalServerError, "Error creating auth url: %s", err) + return + } + + url, err := session.GetAuthURL() + if err != nil { + c.String(http.StatusInternalServerError, "Error getting auth url: %s", err) + } + + c.Redirect(http.StatusTemporaryRedirect, url) +} + +func Callback(c *gin.Context) { + sessionStore, err := NewSessionManager("libsql://sponsorahackersession-stephanie-gredell.turso.io") + + if err != nil { + panic(err) + } + + user, err := gothic.CompleteUserAuth(c.Writer, c.Request) + if err != nil { + log.Println("Error during user authentication:", err) + c.Redirect(http.StatusTemporaryRedirect, "/") + return + } + c.SetCookie("user_id", user.UserID, 3600, "/", "localhost", false, true) + + // For now, redirect to profile page after successful login + c.Redirect(http.StatusTemporaryRedirect, "/") +} + +func Logout(c *gin.Context) { + c.SetCookie("user_id", "", -1, "/", "localhost", false, true) + c.Redirect(http.StatusTemporaryRedirect, "/") +} diff --git a/go.mod b/go.mod index ecc2287..c3427ea 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,17 @@ go 1.22 require ( github.com/gin-gonic/gin v1.10.0 + github.com/google/uuid v1.6.0 github.com/jmoiron/sqlx v1.4.0 + github.com/joho/godotenv v1.5.1 github.com/markbates/goth v1.80.0 github.com/nicklaw5/helix v1.25.0 github.com/tursodatabase/go-libsql v0.0.0-20241011135853-3effbb6dea5c ) require ( + cloud.google.com/go/compute v1.20.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect @@ -36,6 +40,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect diff --git a/go.sum b/go.sum index 68eed9d..a831a68 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= @@ -42,16 +46,22 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY= +github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE= github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -79,6 +89,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA= +github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/nicklaw5/helix v1.25.0 h1:Mrz537izZVsGdM3I46uGAAlslj61frgkhS/9xQqyT/M= github.com/nicklaw5/helix v1.25.0/go.mod h1:yvXZFapT6afIoxnAvlWiJiUMsYnoHl7tNs+t0bloAMw= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= diff --git a/main.go b/main.go index fc4ad88..0fbdd20 100644 --- a/main.go +++ b/main.go @@ -1,16 +1,14 @@ package main import ( - "fmt" "github.com/gin-gonic/gin" + "github.com/joho/godotenv" "github.com/markbates/goth" - "github.com/markbates/goth/gothic" - "github.com/markbates/goth/providers/google" "github.com/markbates/goth/providers/twitch" - "github.com/markbates/goth/providers/twitter" "log" - "net/http" - "sponsorahacker/db" + "os" + "sponsorahacker/auth" + "sponsorahacker/pages" ) // route to authenticate @@ -20,76 +18,29 @@ func main() { r.LoadHTMLGlob("templates/*") r.Static("/assets", "./assets") - r.GET("/", func(c *gin.Context) { - isLoggedIn := checkIfLoggedIn(c) - fmt.Println("isLoggedIn:", isLoggedIn) - - _, err := db.NewDbClient("libsql://sponsorahacker-stephanie-gredell.turso.io") - if err != nil { - log.Fatal(err) - } - - c.HTML(http.StatusOK, "index.html", gin.H{ - "title": "Sponsor a Hacker", - "isLoggedIn": isLoggedIn, - }) - }) - - r.GET("/apply", func(c *gin.Context) { - c.HTML(http.StatusOK, "apply.html", gin.H{ - "title": "Apply", - }) - }) + err := godotenv.Load() + if err != nil { + log.Fatal("Error loading .env file") + } goth.UseProviders( - twitch.New("3bozqr9birw9qcpdmoeo4my9vjuvoa", "bidyehx9w9csdqqtx95ndpa7zwrjir", "http://localhost:8080/auth/twitch/callback"), - google.New("695096681313-07o8ocke1ifpuim1c9n4k1uacbdvrb4j.apps.googleusercontent.com", "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", "http://localhost:8080/auth/google/callback"), - twitter.New("WSuqS3zaiCFEQOVwXXUq68Duj", "xuIh2dLwXO7P2UeGiBTDUmAfTPqkRdPx4PxwCP88Mj9oSXBg56", "http://localhost:8080/auth/twitter/callback"), + twitch.New(os.Getenv("TWITCH_CLIENT_ID"), os.Getenv("TWITCH_SECRET"), "http://localhost:8080/auth/twitch/callback"), + // google.New(os.Getenv("GOOGLE_CLIENT_ID"), os.Getenv("GOOGLE_SECRET"), "http://localhost:8080/auth/google/callback"), + // twitter.New(os.Getenv("TWITTER_CLIENT_ID"), os.Getenv("TWITTER_SECRET"), "http://localhost:8080/auth/twitter/callback"), ) - r.Use(func(c *gin.Context) { - gothic.GetProviderName = func(req *http.Request) (string, error) { - return "twitch", nil - } - c.Next() - }) - - // do the authentication thing - r.GET("/auth/login/:provider", func(c *gin.Context) { - gothic.BeginAuthHandler(c.Writer, c.Request) - }) - - r.GET("/auth/:provider/callback", func(c *gin.Context) { - user, err := gothic.CompleteUserAuth(c.Writer, c.Request) - if err != nil { - log.Println("Error during user authentication:", err) - c.Redirect(http.StatusTemporaryRedirect, "/homepage") - return - } - c.SetCookie("user_id", user.UserID, 3600, "/", "localhost", false, true) + // auth routes + r.GET("/auth/login/:provider", auth.Login) + r.GET("/auth/:provider/callback", auth.Callback) + r.GET("/auth/logout/:provider", auth.Logout) - // For now, redirect to profile page after successful login - c.Redirect(http.StatusTemporaryRedirect, "/") - }) + // pages routes + r.GET("/", pages.Home) + r.GET("/login", pages.Login) - // do the logout thang - r.GET("/auth/logout/:provider", func(c *gin.Context) { - c.SetCookie("user_id", "", -1, "/", "localhost", false, true) - c.Redirect(http.StatusTemporaryRedirect, "/") - }) + runErr := r.Run(":8080") - err := r.Run(":8080") - - if err != nil { - panic(err) - } -} - -func checkIfLoggedIn(c *gin.Context) bool { - userID, err := c.Cookie("user_id") - if err != nil || userID == "" { - return false + if runErr != nil { + panic(runErr) } - - return true } diff --git a/pages/home.go b/pages/home.go new file mode 100644 index 0000000..452d515 --- /dev/null +++ b/pages/home.go @@ -0,0 +1,41 @@ +package pages + +import ( + "fmt" + "github.com/gin-gonic/gin" + "github.com/joho/godotenv" + "log" + "net/http" + "os" + "sponsorahacker/db" + "sponsorahacker/twitch" + "sponsorahacker/utils" +) + +func Home(c *gin.Context) { + + envErr := godotenv.Load() + if envErr != nil { + log.Fatal("Error loading .env file") + } + isLoggedIn := utils.CheckIfLoggedIn(c) + fmt.Println("isLoggedIn:", isLoggedIn) + + _, err := db.NewDbClient("libsql://sponsorahacker-stephanie-gredell.turso.io") + if err != nil { + log.Fatal(err) + } + + client, twitchErr := twitch.NewTwitchClient(os.Getenv("TWITCH_CLIENT_ID"), os.Getenv("TWITCH_CLIENT_SECRET")) + + if twitchErr != nil { + log.Fatal(twitchErr) + } + + client.GetUser() + + c.HTML(http.StatusOK, "index.html", gin.H{ + "title": "Sponsor a Hacker", + "isLoggedIn": isLoggedIn, + }) +} diff --git a/pages/login.go b/pages/login.go new file mode 100644 index 0000000..a069b93 --- /dev/null +++ b/pages/login.go @@ -0,0 +1,12 @@ +package pages + +import ( + "github.com/gin-gonic/gin" + "net/http" +) + +func Login(c *gin.Context) { + c.HTML(http.StatusOK, "login.html", gin.H{ + "title": "Login", + }) +}