webserver.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package webserver
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "fmt"
  6. "html/template"
  7. "io"
  8. "log"
  9. "math/rand"
  10. "strings"
  11. gamelangpb "git.alfi.li/gamelang/protobuf/gamelang"
  12. "github.com/gorilla/sessions"
  13. "github.com/labstack/echo-contrib/session"
  14. "github.com/labstack/echo/v4"
  15. echolog "github.com/labstack/gommon/log"
  16. )
  17. // Template wraps go's html template
  18. type Template struct {
  19. templates *template.Template
  20. }
  21. // Render renders a Template
  22. func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
  23. return t.templates.ExecuteTemplate(w, name, data)
  24. }
  25. func initTemplates(e *echo.Echo) {
  26. t := &Template{
  27. templates: template.Must(template.ParseGlob("public/*.html")),
  28. }
  29. e.Renderer = t
  30. }
  31. type Config struct {
  32. Http struct {
  33. ListenIP string
  34. ListenPort string
  35. }
  36. }
  37. type Endpoint struct {
  38. Method string
  39. Path string
  40. Callback echo.HandlerFunc
  41. }
  42. type Webserver struct {
  43. config Config
  44. echo *echo.Echo
  45. sessions map[string]gamelangpb.User
  46. }
  47. func NewWebserver(config Config) *Webserver {
  48. // init echo
  49. e := echo.New()
  50. e.Logger.SetLevel(echolog.DEBUG)
  51. e.Logger.Debug("Debug Log enabled")
  52. e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret"))))
  53. initTemplates(e)
  54. log.Print("echo initialized")
  55. ws := Webserver{config: config, echo: e, sessions: map[string]gamelangpb.User{}}
  56. return &ws
  57. }
  58. func (ws *Webserver) NewSession(inputuser gamelangpb.User, ctx echo.Context) string {
  59. newSessionID, _ := randomHex(32)
  60. sess, _ := session.Get("GameLang", ctx)
  61. sess.Values["SessionID"] = newSessionID
  62. sess.Save(ctx.Request(), ctx.Response())
  63. user := gamelangpb.User{}
  64. user.Id = inputuser.Id
  65. user.Name = inputuser.Name
  66. ws.sessions[newSessionID] = user
  67. return newSessionID
  68. }
  69. func (ws *Webserver) CheckSess(ctx echo.Context) (bool, gamelangpb.User) {
  70. sess, err := session.Get("GameLang", ctx)
  71. if err != nil {
  72. log.Print("checkSess: user not logged in")
  73. return false, gamelangpb.User{}
  74. }
  75. sessionID, ok := sess.Values["SessionID"]
  76. if !ok {
  77. log.Print("checkSess: no SessionID value")
  78. return false, gamelangpb.User{}
  79. }
  80. user, ok := ws.sessions[sessionID.(string)]
  81. if !ok {
  82. log.Println("checkSess: no Session found for ID", sessionID.(string))
  83. return false, gamelangpb.User{}
  84. }
  85. return true, user
  86. }
  87. func (ws *Webserver) ListSess() map[string]gamelangpb.User {
  88. return ws.sessions
  89. }
  90. func (ws *Webserver) InitEndpoints(endpoints []Endpoint) error {
  91. for _, endpoint := range endpoints {
  92. switch strings.ToUpper(endpoint.Method) {
  93. case "GET":
  94. ws.echo.GET(endpoint.Path, endpoint.Callback)
  95. case "POST":
  96. ws.echo.POST(endpoint.Path, endpoint.Callback)
  97. default:
  98. return errors.New("method not implemented")
  99. }
  100. }
  101. return nil
  102. }
  103. func (ws *Webserver) Run() {
  104. ws.echo.Logger.Fatal(ws.echo.Start(fmt.Sprintf("%v:%v", ws.config.Http.ListenIP, ws.config.Http.ListenPort)))
  105. }
  106. func randomHex(n int) (string, error) {
  107. bytes := make([]byte, n)
  108. if _, err := rand.Read(bytes); err != nil {
  109. return "", err
  110. }
  111. return hex.EncodeToString(bytes), nil
  112. }