~starkingdoms/starkingdoms

30a2b2f4c9f87bb79c5c585444b6a17ce784a333 — core 2 years ago 7a1e6d3
replace new api
7 files changed, 1 insertions(+), 250 deletions(-)

M .gitignore
D starkingdoms-api/.gitignore
D starkingdoms-api/cmd/starkingdoms-api/main.go
D starkingdoms-api/config.go
D starkingdoms-api/discord.go
D starkingdoms-api/go.mod
D starkingdoms-api/go.sum
M .gitignore => .gitignore +1 -0
@@ 12,3 12,4 @@ assets/final
starkingdoms-client/node_modules
starkingdoms-client/dist
client/node_modules
starkingdoms-api/config.toml
\ No newline at end of file

D starkingdoms-api/.gitignore => starkingdoms-api/.gitignore +0 -1
@@ 1,1 0,0 @@
config.yml
\ No newline at end of file

D starkingdoms-api/cmd/starkingdoms-api/main.go => starkingdoms-api/cmd/starkingdoms-api/main.go +0 -172
@@ 1,172 0,0 @@
package main

import (
	"flag"
	"fmt"
	"github.com/sirupsen/logrus"
	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")

	flag.Parse()

	if *printUsage {
		flag.Usage()
		os.Exit(0)
	}

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

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

	if c.Logging.Format == "json" {
		logrus.SetFormatter(&logrus.JSONFormatter{})
	}
	logrus.SetLevel(c.Logging.Level)

	logrus.WithFields(logrus.Fields{
		"host": c.Server.Host,
		"port": c.Server.Port,
	}).Info("starting http listener")

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

		_, 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))
}

D starkingdoms-api/config.go => starkingdoms-api/config.go +0 -45
@@ 1,45 0,0 @@
package starkingdoms_api

import (
	"github.com/sirupsen/logrus"
	"gopkg.in/yaml.v3"
	"os"
)

type Config struct {
	Server struct {
		Host string `yaml:"host"`
		Port string `yaml:"port"`
	} `yaml:"server"`
	Logging 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) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}

	var cfg Config
	decoder := yaml.NewDecoder(f)

	err = decoder.Decode(&cfg)
	if err != nil {
		return nil, err
	}

	err = f.Close()
	if err != nil {
		return nil, err
	}

	return &cfg, nil
}

D starkingdoms-api/discord.go => starkingdoms-api/discord.go +0 -10
@@ 1,10 0,0 @@
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)
}

D starkingdoms-api/go.mod => starkingdoms-api/go.mod +0 -9
@@ 1,9 0,0 @@
module gitlab.com/starkingdoms.tk/starkingdoms.tk/starkingdoms-api

go 1.21.3

require (
	github.com/sirupsen/logrus v1.9.3 // indirect
	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)

D starkingdoms-api/go.sum => starkingdoms-api/go.sum +0 -13
@@ 1,13 0,0 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=