package main import ( "log" "math/rand" "net/http" "strings" ws "git.alfi.li/gamelang/frontend/webserver" gamelangpb "git.alfi.li/gamelang/protobuf/gamelang" um "git.alfi.li/gamelang/systems/usermanager" wm "git.alfi.li/gamelang/systems/worldmanager" "github.com/labstack/echo/v4" gcfg "gopkg.in/gcfg.v1" ) type ExampleConfig struct { Http struct { Listen string // ip:port } Kafka struct { Enabled bool UserManagerBroker string WorldManagerBroker string } } func DefaultConfig() ExampleConfig { config := ExampleConfig{} config.Http.Listen = "0.0.0.0:8080" config.Kafka.Enabled = false return config } type exampleWebServer struct { webserver ws.Webserver usermanager um.UserManager worldmanager wm.WorldManager } func (ews exampleWebServer) RenderEndpoints() []ws.Endpoint { endpoints := []ws.Endpoint{} endpoints = append(endpoints, ws.Endpoint{"GET", "/", func(ctx echo.Context) error { log.Print("/: get") ok, user := ews.webserver.CheckSess(ctx) if !ok { log.Print("/: not found") return ctx.Redirect(301, "/login") } data := struct { Username string Worlds []gamelangpb.World Items []string }{ Username: user.Name, Worlds: ews.worldmanager.List(), Items: []string{ "user", "world", }, } log.Printf("/: user \"%v\" found", user.Name) return ctx.Render(http.StatusOK, "index", data) }}) endpoints = append(endpoints, ws.Endpoint{"GET", "/user", func(ctx echo.Context) error { log.Print("/user: get") log.Print("/user: sending register form") return ctx.Render(http.StatusOK, "registerform", "") }}) // POST to /user creates a user endpoints = append(endpoints, ws.Endpoint{"POST", "/user", func(ctx echo.Context) error { username := ctx.FormValue("username") password := ctx.FormValue("password") log.Printf("new user request: %v", username) user, err := ews.usermanager.Create(rand.Uint32(), username, password) if err != nil { return ctx.String(501, "user creation failed") } ews.webserver.NewSession(user, ctx) log.Printf("new user created: %v", username) return ctx.Redirect(302, "/") }}) endpoints = append(endpoints, ws.Endpoint{"GET", "/login", func(ctx echo.Context) error { log.Print("/login: get") // check if the login page was called with failed parameter (set by /login POST) failedBefore := false if value := ctx.FormValue("failed"); value == "1" { failedBefore = true } ok, user := ews.webserver.CheckSess(ctx) if ok { // logged in log.Printf("/login: user %v logged in", user.Name) return ctx.String(http.StatusOK, "hello, "+user.Name+"\nyou are logged in.") } // not logged in log.Print("/login: not logged in") return ctx.Render(http.StatusOK, "loginform", failedBefore) }}) endpoints = append(endpoints, ws.Endpoint{"POST", "/login", func(ctx echo.Context) error { username := ctx.FormValue("username") password := ctx.FormValue("password") // if the session is already set, the user is already logged in ok, _ := ews.webserver.CheckSess(ctx) if ok { return ctx.String(http.StatusOK, "you are already logged in.") } log.Printf("user login attempt: %v", username) user := gamelangpb.User{} user, ok = ews.usermanager.Check(username, password) if ok { ews.webserver.NewSession(user, ctx) log.Printf("user login suceeded: %v", username) return ctx.String(http.StatusOK, "hello, "+username+"\nyou are now logged in.") } log.Printf("user login failed: %v", username) return ctx.Redirect(302, "/login?failed=1") }}) endpoints = append(endpoints, ws.Endpoint{"GET", "/admin", func(ctx echo.Context) error { log.Print("/admin: get") ok, user := ews.webserver.CheckSess(ctx) if !ok { log.Print("/admin: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } log.Println("/admin:", user.Name) if user.Admin != true && user.Name != "admin" { log.Println("/admin: user is not an admin", user.Name) return ctx.String(http.StatusUnauthorized, "you are not an admin") } data := struct { Users []gamelangpb.User Sessions map[string]gamelangpb.User Worlds []gamelangpb.World }{ Users: ews.usermanager.List(), Sessions: ews.webserver.ListSess(), Worlds: ews.worldmanager.List(), } err := ctx.Render(http.StatusOK, "admin", data) if err != nil { log.Println(err) } return err }}) // worldbuilder // Get to /World returns register form endpoints = append(endpoints, ws.Endpoint{"GET", "/world", func(ctx echo.Context) error { ok, _ := ews.webserver.CheckSess(ctx) if !ok { log.Print("/World: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } data := struct { Worlds []gamelangpb.World }{ Worlds: ews.worldmanager.List(), } err := ctx.Render(http.StatusOK, "worldlobby", data) if err != nil { log.Print(err) } return err }}) endpoints = append(endpoints, ws.Endpoint{"POST", "/world", func(ctx echo.Context) error { ok, _ := ews.webserver.CheckSess(ctx) if !ok { log.Print("/World: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } worldname := ctx.FormValue("worldname") for _, world := range ews.worldmanager.List() { if worldname == world.Name { log.Printf("world \"%s\" already exists", worldname) return ctx.String(http.StatusAlreadyReported, "world already exists") } } log.Println("/World: creating world", worldname) _, err := ews.worldmanager.Create(rand.Uint32(), worldname) if err != nil { log.Println("error creating world", err) return ctx.String(http.StatusInternalServerError, "error creating world") } return ctx.Redirect(http.StatusFound, "/world") }}) endpoints = append(endpoints, ws.Endpoint{"POST", "/world/join", func(ctx echo.Context) error { log.Print("join attemt") ok, user := ews.webserver.CheckSess(ctx) if !ok { log.Print("/World/join: not logged in") return ctx.String(http.StatusUnauthorized, "not logged in") } worldname := ctx.FormValue("worldname") log.Println("joining", user.Name, "to", worldname) err := ews.worldmanager.Join(worldname, &user) if err != nil { log.Printf("error joining %s to %s", user.Name, worldname) return ctx.String(501, "join failed") } log.Println("join of", user.Name, "to", worldname, "complete") return ctx.Redirect(302, "/world") }}) return endpoints } func main() { var config ExampleConfig err := gcfg.ReadFileInto(&config, "config") if err != nil { if strings.Count(err.Error(), "no such file or directory") > 0 { config = DefaultConfig() } else { log.Fatal(err) } } log.Print("config read") log.Printf("%+v", config) // init usermanager brokers := []string{} if config.Kafka.Enabled { brokers = strings.Split(config.Kafka.UserManagerBroker, ",") } usermanager := um.NewUserManager(brokers) log.Print("usermanager initialized") brokers = []string{} if config.Kafka.Enabled { brokers = strings.Split(config.Kafka.WorldManagerBroker, ",") } worldmanager := wm.NewWorldManager(brokers) log.Print("worldmanager initialized") wsConfig := ws.Config{} listen := strings.Split(config.Http.Listen, ":") wsConfig.Http.ListenIP = listen[0] wsConfig.Http.ListenPort = listen[1] webserver := ws.NewWebserver(wsConfig) log.Print("webserver initialized") Ws := exampleWebServer{webserver: *webserver, usermanager: *usermanager, worldmanager: *worldmanager} Ws.webserver.InitEndpoints(Ws.RenderEndpoints()) Ws.webserver.Run() }