123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- 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()
- }
|