~starkingdoms/starkingdoms

0f412a19d7d3ca27558ef5721e6f36de739ad38e — ghostlyzsh 2 years ago ef5971d + 7a1e6d3
Merge branch 'bevy_rewrite' of https://gitlab.com/starkingdoms.tk/starkingdoms.tk into bevy_rewrite
M starkingdoms-api/cmd/starkingdoms-api/main.go => starkingdoms-api/cmd/starkingdoms-api/main.go +122 -2
@@ 4,11 4,25 @@ import (
	"flag"
	"fmt"
	"github.com/sirupsen/logrus"
	starkingdoms_api "gitlab.com/starkingdoms.tk/starkingdoms.tk/starkingdoms-api"
	starkingdomsapi "gitlab.com/starkingdoms.tk/starkingdoms.tk/starkingdoms-api"
	"io"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"strings"
)

var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

func randSeq(n int) string {
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

func main() {
	configPath := flag.String("config", "config.yml", "File to load configuration file from")
	printUsage := flag.Bool("help", false, "Show command line usage")


@@ 20,7 34,7 @@ func main() {
		os.Exit(0)
	}

	c, err := starkingdoms_api.LoadConfig(*configPath)
	c, err := starkingdomsapi.LoadConfig(*configPath)

	if err != nil {
		fmt.Printf("failed to load config: %s", err)


@@ 45,7 59,113 @@ func main() {
		_, err := fmt.Fprintf(w, "pong")
		if err != nil {
			logrus.Error(err)
			return
		}
	})

	var stateMap = make(map[string]string)

	http.HandleFunc("/discord/start", func(w http.ResponseWriter, r *http.Request) {
		logrus.WithFields(logrus.Fields{
			"remote": r.RemoteAddr,
		}).Info("GET /discord/start")

		redirectUri := r.URL.Query().Get("back")
		if redirectUri == "" {
			_, err := fmt.Fprintf(w, "Missing `back` parameter.")
			if err != nil {
				logrus.Error(err)
				return
			}
			return
		}

		state := randSeq(20)
		stateMap[state] = redirectUri
		discordUrl := starkingdomsapi.DiscordApiUrl(c, state)
		http.Redirect(w, r, discordUrl, http.StatusFound)
	})

	http.HandleFunc("/discord/callback", func(w http.ResponseWriter, r *http.Request) {
		logrus.WithFields(logrus.Fields{
			"remote": r.RemoteAddr,
		}).Info("GET /discord/callback")

		code := r.URL.Query().Get("code")
		if code == "" {
			_, err := fmt.Fprintf(w, "Missing `code` parameter.")
			if err != nil {
				logrus.Error(err)
				return
			}
			return
		}

		state := r.URL.Query().Get("state")
		if state == "" {
			_, err := fmt.Fprintf(w, "Missing `state` parameter.")
			if err != nil {
				logrus.Error(err)
				return
			}
			return
		}

		_, ok := stateMap[state]
		if !ok {
			_, err := fmt.Fprintf(w, "Invalid `state` parameter, cannot redirect back. Perhaps your login expired? Try starting over from the main login page.")
			if err != nil {
				logrus.Error(err)
				return
			}
		}

		delete(stateMap, state)

		client := &http.Client{}

		v := url.Values{
			"grant_type":   {"authorization_code"},
			"code":         {code},
			"redirect_uri": {c.Discord.RedirectURI},
		}

		logrus.WithFields(logrus.Fields{
			"sendingBody": v.Encode(),
		}).Info("sending token request")

		req, err := http.NewRequest("POST", "https://discord.com/api/v10/oauth2/token", strings.NewReader(v.Encode()))

		if err != nil {
			logrus.Error(err)
			return
		}

		req.Header.Set("Accept", "application/json")
		req.SetBasicAuth(c.Discord.ClientID, c.Discord.ClientSecret)

		resp, err := client.Do(req)
		defer func(Body io.ReadCloser) {
			err := Body.Close()
			if err != nil {
				logrus.Error(err)
				return
			}
		}(resp.Body)

		if err != nil {
			logrus.Error(err)
			return
		}

		b, err := io.ReadAll(resp.Body)
		if err != nil {
			logrus.Fatal(err)
		}

		logrus.WithFields(logrus.Fields{
			"resp": string(b),
		}).Info("got authentication token")
	})

	logrus.Error(http.ListenAndServe(c.Server.Host+":"+c.Server.Port, nil))

M starkingdoms-api/config.go => starkingdoms-api/config.go +5 -0
@@ 15,6 15,11 @@ type Config struct {
		Format string       `yaml:"format"`
		Level  logrus.Level `yaml:"level"`
	} `yaml:"logging"`
	Discord struct {
		ClientID     string `yaml:"client_id"`
		ClientSecret string `yaml:"client_secret"`
		RedirectURI  string `yaml:"redirect_uri"`
	} `yaml:"discord"`
}

func LoadConfig(path string) (*Config, error) {

A starkingdoms-api/discord.go => starkingdoms-api/discord.go +10 -0
@@ 0,0 1,10 @@
package starkingdoms_api

import (
	"fmt"
	"net/url"
)

func DiscordApiUrl(c *Config, state string) string {
	return fmt.Sprintf("https://discord.com/api/oauth2/authorize?client_id=%s&redirect_uri=%s&response_type=code&scope=identify&state=%s", c.Discord.ClientID, url.QueryEscape(c.Discord.RedirectURI), state)
}