package webserver import ( "encoding/hex" "errors" "fmt" "html/template" "io" "log" "math/rand" "strings" gamelangpb "git.alfi.li/gamelang/protobuf/gamelang" "github.com/gorilla/sessions" "github.com/labstack/echo-contrib/session" "github.com/labstack/echo/v4" echolog "github.com/labstack/gommon/log" ) // Template wraps go's html template type Template struct { templates *template.Template } // Render renders a Template func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error { return t.templates.ExecuteTemplate(w, name, data) } func initTemplates(e *echo.Echo) { t := &Template{ templates: template.Must(template.ParseGlob("public/*.html")), } e.Renderer = t } type Config struct { Http struct { ListenIP string ListenPort string } } type Endpoint struct { Method string Path string Callback echo.HandlerFunc } type Webserver struct { config Config echo *echo.Echo sessions map[string]gamelangpb.User } func NewWebserver(config Config) *Webserver { // init echo e := echo.New() e.Logger.SetLevel(echolog.DEBUG) e.Logger.Debug("Debug Log enabled") e.Use(session.Middleware(sessions.NewCookieStore([]byte("secret")))) initTemplates(e) log.Print("echo initialized") ws := Webserver{config: config, echo: e, sessions: map[string]gamelangpb.User{}} return &ws } func (ws *Webserver) NewSession(inputuser gamelangpb.User, ctx echo.Context) string { newSessionID, _ := randomHex(32) sess, _ := session.Get("GameLang", ctx) sess.Values["SessionID"] = newSessionID sess.Save(ctx.Request(), ctx.Response()) user := gamelangpb.User{} user.Id = inputuser.Id user.Name = inputuser.Name ws.sessions[newSessionID] = user return newSessionID } func (ws *Webserver) CheckSess(ctx echo.Context) (bool, gamelangpb.User) { sess, err := session.Get("GameLang", ctx) if err != nil { log.Print("checkSess: user not logged in") return false, gamelangpb.User{} } sessionID, ok := sess.Values["SessionID"] if !ok { log.Print("checkSess: no SessionID value") return false, gamelangpb.User{} } user, ok := ws.sessions[sessionID.(string)] if !ok { log.Println("checkSess: no Session found for ID", sessionID.(string)) return false, gamelangpb.User{} } return true, user } func (ws *Webserver) ListSess() map[string]gamelangpb.User { return ws.sessions } func (ws *Webserver) InitEndpoints(endpoints []Endpoint) error { for _, endpoint := range endpoints { switch strings.ToUpper(endpoint.Method) { case "GET": ws.echo.GET(endpoint.Path, endpoint.Callback) case "POST": ws.echo.POST(endpoint.Path, endpoint.Callback) default: return errors.New("method not implemented") } } return nil } func (ws *Webserver) Run() { ws.echo.Logger.Fatal(ws.echo.Start(fmt.Sprintf("%v:%v", ws.config.Http.ListenIP, ws.config.Http.ListenPort))) } func randomHex(n int) (string, error) { bytes := make([]byte, n) if _, err := rand.Read(bytes); err != nil { return "", err } return hex.EncodeToString(bytes), nil }