From 46b1279852e119ce4e570901193307b94240dffe Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Wed, 21 Aug 2024 22:58:54 +0100 Subject: [PATCH 01/15] feat: Add admin Discord link endpoint --- api/account/discord.go | 37 ++++++++++++++++++++++++++++++++++++- api/account/info.go | 4 +++- api/common.go | 3 +++ api/endpoints.go | 40 +++++++++++++++++++++++++++++++++++++++- db/account.go | 28 ++++++++++++++++++++++++++++ go.mod | 6 +++++- go.sum | 10 ++++++++++ rogueserver.go | 4 ++++ 8 files changed, 128 insertions(+), 4 deletions(-) diff --git a/api/account/discord.go b/api/account/discord.go index 792afe6..29affb3 100644 --- a/api/account/discord.go +++ b/api/account/discord.go @@ -22,12 +22,17 @@ import ( "errors" "net/http" "net/url" + + "github.com/bwmarrin/discordgo" ) var ( DiscordClientID string DiscordClientSecret string DiscordCallbackURL string + + DiscordSession *discordgo.Session + DiscordGuildId string ) func HandleDiscordCallback(w http.ResponseWriter, r *http.Request) (string, error) { @@ -36,7 +41,6 @@ func HandleDiscordCallback(w http.ResponseWriter, r *http.Request) (string, erro http.Redirect(w, r, GameURL, http.StatusSeeOther) return "", errors.New("code is empty") } - discordId, err := RetrieveDiscordId(code) if err != nil { http.Redirect(w, r, GameURL, http.StatusSeeOther) @@ -106,3 +110,34 @@ func RetrieveDiscordId(code string) (string, error) { return user.Id, nil } + +func IsUserDiscordAdmin(discordId string, discordGuildId string) (bool, error) { + // fetch all roles from discord + roles, err := DiscordSession.GuildRoles(discordGuildId) + if err != nil { + return false, err + } + + // fetch all roles from user + userRoles, err := DiscordSession.GuildMember(discordGuildId, discordId) + if err != nil { + return false, err + } + + // check if user has a "Dev" or a "Division Heads" role + var hasRole bool + for _, role := range userRoles.Roles { + for _, guildRole := range roles { + if role == guildRole.ID && (guildRole.Name == "Dev" || guildRole.Name == "Division Heads") { + hasRole = true + break + } + } + } + + if !hasRole { + return false, nil + } + + return true, nil +} diff --git a/api/account/info.go b/api/account/info.go index 6802238..2d29a78 100644 --- a/api/account/info.go +++ b/api/account/info.go @@ -26,16 +26,18 @@ type InfoResponse struct { DiscordId string `json:"discordId"` GoogleId string `json:"googleId"` LastSessionSlot int `json:"lastSessionSlot"` + HasAdminRole bool `json:"hasAdminRole"` } // /account/info - get account info -func Info(username string, discordId string, googleId string, uuid []byte) (InfoResponse, error) { +func Info(username string, discordId string, googleId string, uuid []byte, hasAdminRole bool) (InfoResponse, error) { slot, _ := db.GetLatestSessionSaveDataSlot(uuid) response := InfoResponse{ Username: username, LastSessionSlot: slot, DiscordId: discordId, GoogleId: googleId, + HasAdminRole: hasAdminRole, } return response, nil } diff --git a/api/common.go b/api/common.go index 7e3c2aa..d9b26ae 100644 --- a/api/common.go +++ b/api/common.go @@ -66,6 +66,9 @@ func Init(mux *http.ServeMux) error { // auth mux.HandleFunc("/auth/{provider}/callback", handleProviderCallback) mux.HandleFunc("/auth/{provider}/logout", handleProviderLogout) + + // admin + mux.HandleFunc("POST /admin/account/discord-link", handleAdminDiscordLink) return nil } diff --git a/api/endpoints.go b/api/endpoints.go index b9802fe..7d7924a 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -68,7 +68,10 @@ func handleAccountInfo(w http.ResponseWriter, r *http.Request) { return } } - response, err := account.Info(username, discordId, googleId, uuid) + + hasAdminRole, _ := account.IsUserDiscordAdmin(discordId, account.DiscordGuildId) + + response, err := account.Info(username, discordId, googleId, uuid, hasAdminRole) if err != nil { httpError(w, r, err, http.StatusInternalServerError) return @@ -660,3 +663,38 @@ func handleProviderLogout(w http.ResponseWriter, r *http.Request) { } w.WriteHeader(http.StatusOK) } + +func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + httpError(w, r, fmt.Errorf("failed to parse request form: %s", err), http.StatusBadRequest) + return + } + + uuid, err := uuidFromRequest(r) + if err != nil { + httpError(w, r, err, http.StatusUnauthorized) + return + } + + userDiscordId, err := db.FetchDiscordIdByUUID(uuid) + if err != nil { + httpError(w, r, err, http.StatusUnauthorized) + return + } + + hasRole, err := account.IsUserDiscordAdmin(userDiscordId, account.DiscordGuildId) + + if !hasRole || err != nil { + httpError(w, r, fmt.Errorf("user does not have the required role"), http.StatusForbidden) + return + } + + err = db.AddDiscordIdByUsername(r.Form.Get("discordId"), r.Form.Get("username")) + if err != nil { + httpError(w, r, err, http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) +} diff --git a/db/account.go b/db/account.go index d463211..d628df7 100644 --- a/db/account.go +++ b/db/account.go @@ -116,6 +116,34 @@ func FetchGoogleIdByUsername(username string) (string, error) { return googleId.String, nil } +func FetchDiscordIdByUUID(uuid []byte) (string, error) { + var discordId sql.NullString + err := handle.QueryRow("SELECT discordId FROM accounts WHERE uuid = ?", uuid).Scan(&discordId) + if err != nil { + return "", err + } + + if !discordId.Valid { + return "", nil + } + + return discordId.String, nil +} + +func FetchGoogleIdByUUID(uuid []byte) (string, error) { + var googleId sql.NullString + err := handle.QueryRow("SELECT googleId FROM accounts WHERE uuid = ?", uuid).Scan(&googleId) + if err != nil { + return "", err + } + + if !googleId.Valid { + return "", nil + } + + return googleId.String, nil +} + func FetchUsernameBySessionToken(token []byte) (string, error) { var username string err := handle.QueryRow("SELECT a.username FROM accounts a JOIN sessions s ON a.uuid = s.uuid WHERE s.token = ?", token).Scan(&username) diff --git a/go.mod b/go.mod index 04ae233..14f1e75 100644 --- a/go.mod +++ b/go.mod @@ -13,4 +13,8 @@ require ( github.com/klauspost/compress v1.17.9 ) -require golang.org/x/sys v0.19.0 // indirect +require ( + github.com/bwmarrin/discordgo v0.28.1 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + golang.org/x/sys v0.19.0 // indirect +) diff --git a/go.sum b/go.sum index 7e0a6c3..51feab8 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,22 @@ +github.com/bwmarrin/discordgo v0.28.1 h1:gXsuo2GBO7NbR6uqmrrBDplPUx2T3nzu775q/Rd1aG4= +github.com/bwmarrin/discordgo v0.28.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/rogueserver.go b/rogueserver.go index 0b007ae..2706813 100644 --- a/rogueserver.go +++ b/rogueserver.go @@ -25,6 +25,7 @@ import ( "net/http" "os" + "github.com/bwmarrin/discordgo" "github.com/pagefaultgames/rogueserver/api" "github.com/pagefaultgames/rogueserver/api/account" "github.com/pagefaultgames/rogueserver/db" @@ -55,6 +56,8 @@ func main() { gameurl := flag.String("gameurl", "https://pokerogue.net", "URL for game server") + discordbottoken := flag.String("discordbottoken", "dbt", "Discord Bot Token") + flag.Parse() account.GameURL = *gameurl @@ -66,6 +69,7 @@ func main() { account.GoogleClientID = *googleclientid account.GoogleClientSecret = *googlesecretid account.GoogleCallbackURL = *callbackurl + "/auth/google/callback" + account.DiscordSession, _ = discordgo.New("Bot " + *discordbottoken) // register gob types gob.Register([]interface{}{}) From ad469a5c6174a17f6f48adba9fa3162e48adc8b8 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Thu, 29 Aug 2024 23:12:32 +0100 Subject: [PATCH 02/15] feat: Add Discord Guild ID flag to server configuration --- rogueserver.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rogueserver.go b/rogueserver.go index 2706813..c64aea9 100644 --- a/rogueserver.go +++ b/rogueserver.go @@ -57,6 +57,7 @@ func main() { gameurl := flag.String("gameurl", "https://pokerogue.net", "URL for game server") discordbottoken := flag.String("discordbottoken", "dbt", "Discord Bot Token") + discordguildid := flag.String("discordguildid", "dgid", "Discord Guild ID") flag.Parse() @@ -70,7 +71,7 @@ func main() { account.GoogleClientSecret = *googlesecretid account.GoogleCallbackURL = *callbackurl + "/auth/google/callback" account.DiscordSession, _ = discordgo.New("Bot " + *discordbottoken) - + account.DiscordGuildId = *discordguildid // register gob types gob.Register([]interface{}{}) gob.Register(map[string]interface{}{}) From f609ec5ee8663fef717d69dfa3efb19cce26039d Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Fri, 30 Aug 2024 01:16:02 +0100 Subject: [PATCH 03/15] feat: Add logging for Discord ID addition in admin Discord link endpoint --- api/endpoints.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/endpoints.go b/api/endpoints.go index 7d7924a..0e7cb3a 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -695,6 +695,6 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { httpError(w, r, err, http.StatusInternalServerError) return } - + fmt.Printf("%s added discord id %s to username %s", userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) w.WriteHeader(http.StatusOK) } From 715fe9344039ea82b02fe277c84aeb483c366d41 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:30:46 +0100 Subject: [PATCH 04/15] chore: Update variable name for Discord guild ID in account package --- api/account/discord.go | 8 ++++---- api/endpoints.go | 4 ++-- rogueserver.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/account/discord.go b/api/account/discord.go index 29affb3..9e4ce8c 100644 --- a/api/account/discord.go +++ b/api/account/discord.go @@ -32,7 +32,7 @@ var ( DiscordCallbackURL string DiscordSession *discordgo.Session - DiscordGuildId string + DiscordGuildID string ) func HandleDiscordCallback(w http.ResponseWriter, r *http.Request) (string, error) { @@ -111,15 +111,15 @@ func RetrieveDiscordId(code string) (string, error) { return user.Id, nil } -func IsUserDiscordAdmin(discordId string, discordGuildId string) (bool, error) { +func IsUserDiscordAdmin(discordId string, discordGuildID string) (bool, error) { // fetch all roles from discord - roles, err := DiscordSession.GuildRoles(discordGuildId) + roles, err := DiscordSession.GuildRoles(discordGuildID) if err != nil { return false, err } // fetch all roles from user - userRoles, err := DiscordSession.GuildMember(discordGuildId, discordId) + userRoles, err := DiscordSession.GuildMember(discordGuildID, discordId) if err != nil { return false, err } diff --git a/api/endpoints.go b/api/endpoints.go index 0e7cb3a..3009041 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -69,7 +69,7 @@ func handleAccountInfo(w http.ResponseWriter, r *http.Request) { } } - hasAdminRole, _ := account.IsUserDiscordAdmin(discordId, account.DiscordGuildId) + hasAdminRole, _ := account.IsUserDiscordAdmin(discordId, account.DiscordGuildID) response, err := account.Info(username, discordId, googleId, uuid, hasAdminRole) if err != nil { @@ -683,7 +683,7 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { return } - hasRole, err := account.IsUserDiscordAdmin(userDiscordId, account.DiscordGuildId) + hasRole, err := account.IsUserDiscordAdmin(userDiscordId, account.DiscordGuildID) if !hasRole || err != nil { httpError(w, r, fmt.Errorf("user does not have the required role"), http.StatusForbidden) diff --git a/rogueserver.go b/rogueserver.go index c64aea9..c02df26 100644 --- a/rogueserver.go +++ b/rogueserver.go @@ -71,7 +71,7 @@ func main() { account.GoogleClientSecret = *googlesecretid account.GoogleCallbackURL = *callbackurl + "/auth/google/callback" account.DiscordSession, _ = discordgo.New("Bot " + *discordbottoken) - account.DiscordGuildId = *discordguildid + account.DiscordGuildID = *discordguildid // register gob types gob.Register([]interface{}{}) gob.Register(map[string]interface{}{}) From fd57ad36fba0bf48263c3066b340bfb260e8209e Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:41:06 +0100 Subject: [PATCH 05/15] chore: Add logging for Discord ID addition in admin Discord link endpoint --- api/endpoints.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/endpoints.go b/api/endpoints.go index 3009041..10df3fb 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -23,6 +23,7 @@ import ( "encoding/json" "errors" "fmt" + "log" "net/http" "strconv" "strings" @@ -684,7 +685,6 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { } hasRole, err := account.IsUserDiscordAdmin(userDiscordId, account.DiscordGuildID) - if !hasRole || err != nil { httpError(w, r, fmt.Errorf("user does not have the required role"), http.StatusForbidden) return @@ -695,6 +695,6 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { httpError(w, r, err, http.StatusInternalServerError) return } - fmt.Printf("%s added discord id %s to username %s", userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) + log.Printf("%s added discord id %s to username %s", userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) w.WriteHeader(http.StatusOK) } From de2e74ce5ee61f269dedaaec83ca2e39d27595b9 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:43:22 +0100 Subject: [PATCH 06/15] chore: Add admin Discord link endpoint --- api/common.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api/common.go b/api/common.go index d9b26ae..6abad39 100644 --- a/api/common.go +++ b/api/common.go @@ -69,6 +69,7 @@ func Init(mux *http.ServeMux) error { // admin mux.HandleFunc("POST /admin/account/discord-link", handleAdminDiscordLink) + return nil } From 2d166d44b77be6cd3d9f85b9a69de7864ed9ad52 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:43:58 +0100 Subject: [PATCH 07/15] chore: Add logging for Discord ID addition in admin Discord link endpoint --- api/endpoints.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/endpoints.go b/api/endpoints.go index 10df3fb..1dcac35 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -695,6 +695,8 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { httpError(w, r, err, http.StatusInternalServerError) return } + log.Printf("%s added discord id %s to username %s", userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) + w.WriteHeader(http.StatusOK) } From 536568180ed2322444c20c1fb0e767eafc7d23da Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:48:34 +0100 Subject: [PATCH 08/15] chore: Remove unnecessary code in handleAdminDiscordLink function --- api/endpoints.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/api/endpoints.go b/api/endpoints.go index 1dcac35..02e762e 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -666,12 +666,6 @@ func handleProviderLogout(w http.ResponseWriter, r *http.Request) { } func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { - err := r.ParseForm() - if err != nil { - httpError(w, r, fmt.Errorf("failed to parse request form: %s", err), http.StatusBadRequest) - return - } - uuid, err := uuidFromRequest(r) if err != nil { httpError(w, r, err, http.StatusUnauthorized) From 0b90619cdbda266f72783285ac05212dde030292 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:53:41 +0100 Subject: [PATCH 09/15] chore: Update logging format in handleAdminDiscordLink function --- api/endpoints.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/endpoints.go b/api/endpoints.go index 02e762e..fcff054 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -690,7 +690,6 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { return } - log.Printf("%s added discord id %s to username %s", userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) - + log.Printf("%s: %s added discord id %s to username %s", r.URL.Path, userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) w.WriteHeader(http.StatusOK) } From 070436585e4a7fe6d0f47d4e4aba763509227bb4 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 03:54:32 +0100 Subject: [PATCH 10/15] chore: Refactor handleAdminDiscordLink function for improved logging --- api/endpoints.go | 1 + 1 file changed, 1 insertion(+) diff --git a/api/endpoints.go b/api/endpoints.go index fcff054..adddad1 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -691,5 +691,6 @@ func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { } log.Printf("%s: %s added discord id %s to username %s", r.URL.Path, userDiscordId, r.Form.Get("discordId"), r.Form.Get("username")) + w.WriteHeader(http.StatusOK) } From d9caefed7198f7b1293d6255cfddf25b586f691b Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 04:06:27 +0100 Subject: [PATCH 11/15] chore: Update Discord Bot Token and Discord Guild ID flags in server configuration --- rogueserver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rogueserver.go b/rogueserver.go index c02df26..157f92e 100644 --- a/rogueserver.go +++ b/rogueserver.go @@ -56,8 +56,8 @@ func main() { gameurl := flag.String("gameurl", "https://pokerogue.net", "URL for game server") - discordbottoken := flag.String("discordbottoken", "dbt", "Discord Bot Token") - discordguildid := flag.String("discordguildid", "dgid", "Discord Guild ID") + discordbottoken := flag.String("discordbottoken", "", "Discord Bot Token") + discordguildid := flag.String("discordguildid", "", "Discord Guild ID") flag.Parse() From dff7579360330e9ea291a1b4fa434c779d2a6928 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 04:39:08 +0100 Subject: [PATCH 12/15] chore: Refactor handleAccountInfo function for improved readability and error handling --- api/endpoints.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/api/endpoints.go b/api/endpoints.go index adddad1..dc647a7 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -70,7 +70,10 @@ func handleAccountInfo(w http.ResponseWriter, r *http.Request) { } } - hasAdminRole, _ := account.IsUserDiscordAdmin(discordId, account.DiscordGuildID) + var hasAdminRole bool + if discordId != "" { + hasAdminRole, _ = account.IsUserDiscordAdmin(discordId, account.DiscordGuildID) + } response, err := account.Info(username, discordId, googleId, uuid, hasAdminRole) if err != nil { From 3ccc0006461918e1aabba22c7f6465dbfaec388f Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sun, 1 Sep 2024 20:45:44 +0100 Subject: [PATCH 13/15] chore: Update server configuration flags for Discord Bot Token and Guild ID --- rogueserver.go | 82 +++++++++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/rogueserver.go b/rogueserver.go index 157f92e..c54c6de 100644 --- a/rogueserver.go +++ b/rogueserver.go @@ -19,11 +19,11 @@ package main import ( "encoding/gob" - "flag" "log" "net" "net/http" "os" + "strconv" "github.com/bwmarrin/discordgo" "github.com/pagefaultgames/rogueserver/api" @@ -32,58 +32,56 @@ import ( ) func main() { - // flag stuff - debug := flag.Bool("debug", false, "use debug mode") + // env stuff + debug, _ := strconv.ParseBool(os.Getenv("debug")) - proto := flag.String("proto", "tcp", "protocol for api to use (tcp, unix)") - addr := flag.String("addr", "0.0.0.0:8001", "network address for api to listen on") - tlscert := flag.String("tlscert", "", "tls certificate path") - tlskey := flag.String("tlskey", "", "tls key path") + proto := getEnv("proto", "tcp") + addr := getEnv("addr", "0.0.0.0:8001") + tlscert := getEnv("tlscert", "") + tlskey := getEnv("tlskey", "") - dbuser := flag.String("dbuser", "pokerogue", "database username") - dbpass := flag.String("dbpass", "pokerogue", "database password") - dbproto := flag.String("dbproto", "tcp", "protocol for database connection") - dbaddr := flag.String("dbaddr", "localhost", "database address") - dbname := flag.String("dbname", "pokeroguedb", "database name") + dbuser := getEnv("dbuser", "pokerogue") + dbpass := getEnv("dbpass", "pokerogue") + dbproto := getEnv("dbproto", "tcp") + dbaddr := getEnv("dbaddr", "localhost") + dbname := getEnv("dbname", "pokeroguedb") - discordclientid := flag.String("discordclientid", "dcid", "Discord Oauth2 Client ID") - discordsecretid := flag.String("discordsecretid", "dsid", "Discord Oauth2 Secret ID") + discordclientid := getEnv("discordclientid", "") + discordsecretid := getEnv("discordsecretid", "") - googleclientid := flag.String("googleclientid", "gcid", "Google Oauth2 Client ID") - googlesecretid := flag.String("googlesecretid", "gsid", "Google Oauth2 Secret ID") + googleclientid := getEnv("googleclientid", "") + googlesecretid := getEnv("googlesecretid", "") - callbackurl := flag.String("callbackurl", "http://localhost:8001/", "Callback URL for Oauth2 Client") + callbackurl := getEnv("callbackurl", "http://localhost:8001/") - gameurl := flag.String("gameurl", "https://pokerogue.net", "URL for game server") + gameurl := getEnv("gameurl", "https://pokerogue.net") - discordbottoken := flag.String("discordbottoken", "", "Discord Bot Token") - discordguildid := flag.String("discordguildid", "", "Discord Guild ID") + discordbottoken := getEnv("discordbottoken", "") + discordguildid := getEnv("discordguildid", "") - flag.Parse() + account.GameURL = gameurl - account.GameURL = *gameurl + account.DiscordClientID = discordclientid + account.DiscordClientSecret = discordsecretid + account.DiscordCallbackURL = callbackurl + "/auth/discord/callback" - account.DiscordClientID = *discordclientid - account.DiscordClientSecret = *discordsecretid - account.DiscordCallbackURL = *callbackurl + "/auth/discord/callback" - - account.GoogleClientID = *googleclientid - account.GoogleClientSecret = *googlesecretid - account.GoogleCallbackURL = *callbackurl + "/auth/google/callback" - account.DiscordSession, _ = discordgo.New("Bot " + *discordbottoken) - account.DiscordGuildID = *discordguildid + account.GoogleClientID = googleclientid + account.GoogleClientSecret = googlesecretid + account.GoogleCallbackURL = callbackurl + "/auth/google/callback" + account.DiscordSession, _ = discordgo.New("Bot " + discordbottoken) + account.DiscordGuildID = discordguildid // register gob types gob.Register([]interface{}{}) gob.Register(map[string]interface{}{}) // get database connection - err := db.Init(*dbuser, *dbpass, *dbproto, *dbaddr, *dbname) + err := db.Init(dbuser, dbpass, dbproto, dbaddr, dbname) if err != nil { log.Fatalf("failed to initialize database: %s", err) } // create listener - listener, err := createListener(*proto, *addr) + listener, err := createListener(proto, addr) if err != nil { log.Fatalf("failed to create net listener: %s", err) } @@ -97,14 +95,14 @@ func main() { // start web server handler := prodHandler(mux, gameurl) - if *debug { + if debug { handler = debugHandler(mux) } - if *tlscert == "" { + if tlscert == "" { err = http.Serve(listener, handler) } else { - err = http.ServeTLS(listener, handler, *tlscert, *tlskey) + err = http.ServeTLS(listener, handler, tlscert, tlskey) } if err != nil { log.Fatalf("failed to create http server or server errored: %s", err) @@ -131,11 +129,11 @@ func createListener(proto, addr string) (net.Listener, error) { return listener, nil } -func prodHandler(router *http.ServeMux, clienturl *string) http.Handler { +func prodHandler(router *http.ServeMux, clienturl string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type") w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, GET, POST") - w.Header().Set("Access-Control-Allow-Origin", *clienturl) + w.Header().Set("Access-Control-Allow-Origin", clienturl) if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) @@ -160,3 +158,11 @@ func debugHandler(router *http.ServeMux) http.Handler { router.ServeHTTP(w, r) }) } + +func getEnv(key string, defaultValue string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + + return defaultValue +} From 856ad7aac9ad683f2b06946c6b3e5e66971bd157 Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Mon, 2 Sep 2024 02:06:42 +0100 Subject: [PATCH 14/15] Refactor handleAdminDiscordLink function for improved error handling and logging --- api/endpoints.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/endpoints.go b/api/endpoints.go index dc647a7..d9fb802 100644 --- a/api/endpoints.go +++ b/api/endpoints.go @@ -669,6 +669,12 @@ func handleProviderLogout(w http.ResponseWriter, r *http.Request) { } func handleAdminDiscordLink(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + if err != nil { + httpError(w, r, fmt.Errorf("failed to parse request form: %s", err), http.StatusBadRequest) + return + } + uuid, err := uuidFromRequest(r) if err != nil { httpError(w, r, err, http.StatusUnauthorized) From 248646fa41839a290c4db371cc29bb851768e74f Mon Sep 17 00:00:00 2001 From: Frederico Santos Date: Sat, 14 Sep 2024 01:48:37 +0100 Subject: [PATCH 15/15] feat: Add "Helper" role to Discord admin check for enhanced access control --- api/account/discord.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/account/discord.go b/api/account/discord.go index 9e4ce8c..bf2a00f 100644 --- a/api/account/discord.go +++ b/api/account/discord.go @@ -128,7 +128,7 @@ func IsUserDiscordAdmin(discordId string, discordGuildID string) (bool, error) { var hasRole bool for _, role := range userRoles.Roles { for _, guildRole := range roles { - if role == guildRole.ID && (guildRole.Name == "Dev" || guildRole.Name == "Division Heads") { + if role == guildRole.ID && (guildRole.Name == "Dev" || guildRole.Name == "Division Heads" || guildRole.Name == "Helper") { hasRole = true break }