diff --git a/go.mod b/go.mod index 66d24bc..b857aac 100644 --- a/go.mod +++ b/go.mod @@ -3,17 +3,22 @@ module codegrillathon go 1.22.2 require ( + github.com/gorilla/sessions v1.1.1 + github.com/jmoiron/sqlx v1.4.0 github.com/joho/godotenv v1.5.1 github.com/markbates/goth v1.81.0 + github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d ) require ( + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/coder/websocket v1.8.12 // indirect github.com/go-chi/chi/v5 v5.1.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.6.2 // indirect github.com/gorilla/securecookie v1.1.1 // indirect - github.com/gorilla/sessions v1.1.1 // indirect + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect golang.org/x/oauth2 v0.17.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.32.0 // indirect diff --git a/go.sum b/go.sum index 26fedf1..9dc9e05 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,15 @@ +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= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= +github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= 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/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -17,17 +25,27 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC 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/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/markbates/goth v1.81.0 h1:XVcCkeGWokynPV7MXvgb8pd2s3r7DS40P7931w6kdnE= github.com/markbates/goth v1.81.0/go.mod h1:+6z31QyUms84EHmuBY7iuqYSxyoN3njIgg9iCF/lR1k= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d h1:dOMI4+zEbDI37KGb0TI44GUAwxHF9cMsIoDTJ7UmgfU= +github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d/go.mod h1:l8xTsYB90uaVdMHXMCxKKLSgw5wLYBwBKKefNIUnm9s= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= diff --git a/handlers/auth.go b/handlers/auth.go index e83e98c..eeb9795 100644 --- a/handlers/auth.go +++ b/handlers/auth.go @@ -1,6 +1,7 @@ package handlers import ( + "codegrillathon/internals/database" "fmt" "net/http" @@ -38,12 +39,40 @@ func (h *Handler) Callback(w http.ResponseWriter, r *http.Request) { session, _ := gothic.Store.Get(r, "user-session") session.Values["user_name"] = user.Name session.Values["avatar_url"] = user.AvatarURL + session.Values["user_id"] = user.UserID err = session.Save(r, w) if err != nil { fmt.Printf("error saving the session: %v", err) } + dbClient, err := database.NewDbClient() + + rows, err := dbClient.Query("SELECT COUNT(*) FROM users WHERE username = ? AND provider = ?", user.Name, "twitch") + if err != nil { + fmt.Printf("error checking user in users table: %v\n", err) + } + + defer rows.Close() + + var count int + if rows.Next() { + if err := rows.Scan(&count); err != nil { + fmt.Printf("error with rows: %v", err) + } + } + + if count == 0 { + _, err = dbClient.Exec( + "INSERT INTO users (username, user_cap_id, provider, avatar_url, provider_id) VALUES (?, ?, ?, ?, ?)", + user.Name, 1, "twitch", user.AvatarURL, user.UserID, + ) + + if err != nil { + fmt.Printf("error saving user to database: %v", err) + } + } + http.Redirect(w, r, "/welcome", http.StatusFound) } @@ -66,3 +95,15 @@ func (h *Handler) Logout(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusFound) } + +func RequireAuth(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + session, _ := gothic.Store.Get(r, "user-session") + userID, ok := session.Values["user_id"] + if !ok || userID == nil { + http.Redirect(w, r, "/", http.StatusFound) + return + } + next.ServeHTTP(w, r) + }) +} diff --git a/handlers/hackathon.go b/handlers/hackathon.go new file mode 100644 index 0000000..3665e83 --- /dev/null +++ b/handlers/hackathon.go @@ -0,0 +1,14 @@ +package handlers + +import ( + "fmt" + "net/http" +) + +func (h *Handler) Hackathon(w http.ResponseWriter, r *http.Request) { + fmt.Println("I hit the hackathon route...") + err := h.Template.ExecuteTemplate(w, "hackathon.html", nil) + if err != nil { + http.Error(w, "Template rendering error", http.StatusInternalServerError) + } +} diff --git a/internals/database/dbclient.go b/internals/database/dbclient.go new file mode 100644 index 0000000..7be70f6 --- /dev/null +++ b/internals/database/dbclient.go @@ -0,0 +1,42 @@ +package database + +import ( + "database/sql" + "fmt" + "github.com/jmoiron/sqlx" + _ "github.com/tursodatabase/libsql-client-go/libsql" + "os" +) + +type Database interface { + Query(query string, args ...interface{}) (*sqlx.Rows, error) + Exec(query string, args ...interface{}) (sql.Result, error) + Close() error +} + +type DBClient struct { + db *sqlx.DB +} + +func NewDbClient() (*DBClient, error) { + dsn := os.Getenv("DATABASE_URL") + "?authToken=" + os.Getenv("DATABASE_TOKEN") + db, err := sqlx.Open("libsql", dsn) + if err != nil { + fmt.Printf("error connecting to database: %v", err) + return nil, fmt.Errorf("failed to open db: %w", err) + } + + return &DBClient{db: db}, nil +} + +func (c *DBClient) Query(query string, args ...interface{}) (*sqlx.Rows, error) { + return c.db.Queryx(query, args...) +} + +func (c *DBClient) Exec(query string, args ...interface{}) (sql.Result, error) { + return c.db.Exec(query, args...) +} + +func (c *DBClient) Close() error { + return c.db.Close() +} diff --git a/main.go b/main.go index 3a11ffa..320ce9a 100644 --- a/main.go +++ b/main.go @@ -46,7 +46,8 @@ func main() { // pages route mux.HandleFunc("/", h.Home) - mux.HandleFunc("/welcome", h.Welcome) + mux.Handle("/welcome", handlers.RequireAuth(http.HandlerFunc(h.Welcome))) + mux.HandleFunc("/hackathon", h.Hackathon) server := &http.Server{ Addr: ":8080", diff --git a/todo.md b/todo.md index 147c29e..9540288 100644 --- a/todo.md +++ b/todo.md @@ -2,12 +2,18 @@ userid user_type username capabilities provider avatar_url 1 hacker|repo|streamer codegirl 1,2,3,4,5 twitch|github ... capability_id capability_name -1 join_hackathon +1 join_hacka +2 hackathon_id hackathon_name owner_id 1 something cool 1 +hackathon_cap +id capabilities_id hackathon_id +1 participants userid, hackathon_id +# ACTUAL TODOS +- handle refreshing tokens