diff --git a/.gitignore b/.gitignore index c27f732..616b799 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ static node_modules tmp +config.yml diff --git a/auth/auth.go b/auth/auth.go index 41f2b8b..b081a1f 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -30,28 +30,29 @@ type User interface { // Authorizer handle sesssion type Authorizer struct { - backend UserBackend - cookiejar *sessions.CookieStore - cookieName string - peeper string - cost int + Params +} + +// Params for Authorizer creation +type Params struct { + Backend UserBackend + Cookiejar *sessions.CookieStore + CookieName string + Peeper string + Cost int } // New Authorizer peeper is like a salt but not stored in database, // cost is the bcrypt cost for hashing the password -func New(backend UserBackend, peeper, cookieName, cookieKey string, cost int) *Authorizer { +func New(params Params) *Authorizer { return &Authorizer{ - backend: backend, - cookiejar: sessions.NewCookieStore([]byte(cookieKey)), - cookieName: cookieName, - peeper: peeper, - cost: cost, + Params: params, } } // GenHash generates a new hash from a password func (a *Authorizer) GenHash(password string) (string, error) { - b, err := bcrypt.GenerateFromPassword([]byte(password+a.peeper), a.cost) + b, err := bcrypt.GenerateFromPassword([]byte(password+a.Peeper), a.Cost) if err != nil { return "", err } @@ -60,17 +61,17 @@ func (a *Authorizer) GenHash(password string) (string, error) { // Login cheks password and updates cookie info func (a *Authorizer) Login(rw http.ResponseWriter, req *http.Request, username, password string) error { - cookie, err := a.cookiejar.Get(req, a.cookieName) + cookie, err := a.Cookiejar.Get(req, a.CookieName) if err != nil { return err } - u, err := a.backend.Get(username) + u, err := a.Backend.Get(username) if err != nil { return err } - err = bcrypt.CompareHashAndPassword([]byte(u.GetHash()), []byte(password+a.peeper)) + err = bcrypt.CompareHashAndPassword([]byte(u.GetHash()), []byte(password+a.Peeper)) if err != nil { return ErrInvalidPassword } @@ -78,7 +79,7 @@ func (a *Authorizer) Login(rw http.ResponseWriter, req *http.Request, username, cookie.Values["username"] = username // genereate secret - b, err := bcrypt.GenerateFromPassword([]byte(u.GetHash()), a.cost) + b, err := bcrypt.GenerateFromPassword([]byte(u.GetHash()), a.Cost) if err != nil { return err } @@ -93,12 +94,12 @@ func (a *Authorizer) Login(rw http.ResponseWriter, req *http.Request, username, // RegenSecret update secret in cookie with user info, usefull when updating password func (a *Authorizer) RegenSecret(user User, w http.ResponseWriter, r *http.Request) error { - cookie, err := a.cookiejar.Get(r, a.cookieName) + cookie, err := a.Cookiejar.Get(r, a.CookieName) if err != nil { return err } // genereate secret - b, err := bcrypt.GenerateFromPassword([]byte(user.GetHash()), a.cost) + b, err := bcrypt.GenerateFromPassword([]byte(user.GetHash()), a.Cost) if err != nil { return err } @@ -113,7 +114,7 @@ func (a *Authorizer) RegenSecret(user User, w http.ResponseWriter, r *http.Reque // Logout remove cookie info func (a *Authorizer) Logout(rw http.ResponseWriter, req *http.Request) error { - cookie, err := a.cookiejar.Get(req, a.cookieName) + cookie, err := a.Cookiejar.Get(req, a.CookieName) if err != nil { return err } @@ -129,7 +130,7 @@ func (a *Authorizer) Logout(rw http.ResponseWriter, req *http.Request) error { // CurrentUser returns the logged in username from session func (a *Authorizer) CurrentUser(rw http.ResponseWriter, req *http.Request) (User, error) { - cookie, err := a.cookiejar.Get(req, a.cookieName) + cookie, err := a.Cookiejar.Get(req, a.CookieName) if err != nil { return nil, err } @@ -146,7 +147,7 @@ func (a *Authorizer) CurrentUser(rw http.ResponseWriter, req *http.Request) (Use return nil, ErrCorrupted } - u, err := a.backend.Get(username) + u, err := a.Backend.Get(username) if err != nil { return nil, err } diff --git a/auth/auth_test.go b/auth/auth_test.go index 169ebaa..6a5d08e 100644 --- a/auth/auth_test.go +++ b/auth/auth_test.go @@ -14,7 +14,7 @@ import ( const ( peeper = "polp" - key = "plop" + ckey = "plop" cookieName = "auth" cost = 10 @@ -55,7 +55,7 @@ func getBackend() *Backend { } func login(w http.ResponseWriter, r *http.Request) { - a := New(getBackend(), peeper, cookieName, key, cost) + a := New(getBackend(), peeper, cookieName, ckey, cost) err := a.Login(w, r, username, password) if err != nil { fmt.Fprintf(w, "%s", err) @@ -66,7 +66,7 @@ func login(w http.ResponseWriter, r *http.Request) { } func logout(w http.ResponseWriter, r *http.Request) { - a := New(getBackend(), peeper, cookieName, key, cost) + a := New(getBackend(), peeper, cookieName, ckey, cost) err := a.Logout(w, r) if err != nil { fmt.Fprintf(w, "%s", err) diff --git a/auth/middleware.go b/auth/middleware.go index a52a29a..71af311 100644 --- a/auth/middleware.go +++ b/auth/middleware.go @@ -43,7 +43,7 @@ func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next user := GetCurrentUser(r) if user == nil || !user.HasRole(m.role) { - cookie, err := m.authorizer.cookiejar.Get(r, "rlogin") + cookie, err := m.authorizer.Cookiejar.Get(r, "rlogin") if err != nil { panic(err) } @@ -60,7 +60,7 @@ func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next } func GetPostLoginRedirect(a *Authorizer, w http.ResponseWriter, r *http.Request) (string, error) { - cookie, err := a.cookiejar.Get(r, "rlogin") + cookie, err := a.Cookiejar.Get(r, "rlogin") if err != nil { return "", err } diff --git a/config.yml.exemple b/config.yml.exemple new file mode 100644 index 0000000..05e2870 --- /dev/null +++ b/config.yml.exemple @@ -0,0 +1,8 @@ +authorizer: + cookie_name: auth + cookie_key: mysecretkey + peeper: peeper + cost: 10 +pgdsn: postgres://test:test@127.0.0.1:5432/dev?sslmode=disable +trakttv_client_id: my_trakttv_client_id +listen_port: 3000 diff --git a/config/canape.go b/config/canape.go new file mode 100644 index 0000000..72b937a --- /dev/null +++ b/config/canape.go @@ -0,0 +1,44 @@ +package config + +import ( + "io/ioutil" + "os" + + "gopkg.in/yaml.v2" +) + +type Config struct { + Authorizer AuthorizerConfig `yaml:"authorizer"` + PGDSN string `yaml:"pgdsn"` + Port string `yaml:"listen_port"` + TraktTVClientID string `yaml:"trakttv_client_id"` +} + +type AuthorizerConfig struct { + CookieName string `yaml:"cookie_name"` + Key string `yaml:"cookie_key"` + Peeper string `yaml:"peeper"` + Cost int `yaml:"cost"` +} + +func Load(path string) (*Config, error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + cf := &Config{} + + b, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + err = yaml.Unmarshal(b, cf) + if err != nil { + return nil, err + } + + return cf, nil +} diff --git a/main.go b/main.go index 6cc9250..44b1ff2 100644 --- a/main.go +++ b/main.go @@ -4,12 +4,14 @@ import ( "net/http" "gitlab.quimbo.fr/odwrtw/canape-sql/auth" + "gitlab.quimbo.fr/odwrtw/canape-sql/config" "gitlab.quimbo.fr/odwrtw/canape-sql/movies" "gitlab.quimbo.fr/odwrtw/canape-sql/users" "gitlab.quimbo.fr/odwrtw/canape-sql/web" "github.com/Sirupsen/logrus" "github.com/codegangsta/negroni" + "github.com/gorilla/sessions" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" ) @@ -24,24 +26,44 @@ func (b *UserBackend) Get(username string) (auth.User, error) { func main() { log := logrus.NewEntry(logrus.New()) - - pgdsn := "postgres://test:test@127.0.0.1:5432/dev?sslmode=disable" - db, err := sqlx.Connect("postgres", pgdsn) + cf, err := config.Load("config.yml") if err != nil { log.Panic(err) } - uBackend := &UserBackend{db} - authorizer := auth.New(uBackend, "peeper", "cookieName", "cookieKey", 10) - env := web.NewEnv(db, authorizer, log, "./templates") + db, err := sqlx.Connect("postgres", cf.PGDSN) + if err != nil { + log.Panic(err) + } + uBackend := &UserBackend{Database: db} + + authParams := auth.Params{ + Backend: uBackend, + Peeper: cf.Authorizer.Peeper, + CookieName: cf.Authorizer.CookieName, + Cookiejar: sessions.NewCookieStore([]byte(cf.Authorizer.Key)), + Cost: cf.Authorizer.Cost, + } + authorizer := auth.New(authParams) + + env := web.NewEnv(web.EnvParams{ + Database: db, + Auth: authorizer, + Log: log, + Config: cf, + TemplatesDir: "./templates", + }) + authMiddleware := auth.NewMiddleware(env.Auth) - env.Handle("users.login", "/users/login", users.LoginHandler) - env.Handle("users.logout", "/users/logout", users.LogoutHandler) - env.HandleRole("users.details", "/users/details", users.DetailsHandler, users.UserRole) - env.HandleRole("users.edit", "/users/edit", users.EditHandler, users.UserRole) + env.Handle("/users/login", users.LoginGETHandler).Name("users.login").Methods("GET") + env.Handle("/users/login", users.LoginPOSTHandler).Name("users.login").Methods("POST") + env.Handle("/users/logout", users.LogoutHandler).Name("users.logout") + env.Handle("/users/details", users.DetailsHandler).Name("users.details").WithRole(users.UserRole) + env.Handle("/users/edit", users.EditHandler).Name("users.edit").WithRole(users.UserRole) - env.HandleRole("movies.polochon", "/movies/polochon", movies.FromPolochon, users.UserRole) + env.Handle("/movies/polochon", movies.FromPolochon).Name("movies.polochon").WithRole(users.UserRole) + env.Handle("/movies/explore/popular", movies.ExplorePopular).Name("movies.explore.popular").WithRole(users.UserRole) err = env.SetLoginRoute("users.login") if err != nil { @@ -52,5 +74,5 @@ func main() { n.Use(authMiddleware) n.Use(negroni.NewStatic(http.Dir("./static"))) n.UseHandler(env.Router) - n.Run(":3000") + n.Run(":" + cf.Port) } diff --git a/movies/explorer.go b/movies/explorer.go new file mode 100644 index 0000000..208e590 --- /dev/null +++ b/movies/explorer.go @@ -0,0 +1,7 @@ +package movies + +import "gitlab.quimbo.fr/odwrtw/canape-sql/web" + +func updatePopular(env *web.Env, clientID string) error { + return nil +} diff --git a/movies/handlers.go b/movies/handlers.go index bbc275b..f5afafe 100644 --- a/movies/handlers.go +++ b/movies/handlers.go @@ -2,11 +2,15 @@ package movies import ( "fmt" + "net" "net/http" + "net/url" "github.com/odwrtw/papi" "github.com/odwrtw/polochon/lib" "github.com/odwrtw/polochon/modules/mock" + traktdetailer "github.com/odwrtw/polochon/modules/trakttv" + "github.com/odwrtw/trakttv" "gitlab.quimbo.fr/odwrtw/canape-sql/auth" "gitlab.quimbo.fr/odwrtw/canape-sql/config" @@ -14,6 +18,40 @@ import ( "gitlab.quimbo.fr/odwrtw/canape-sql/web" ) +var ErrPolochonUnavailable = fmt.Errorf("Invalid polochon address") + +func getPolochonMovies(user *users.User) ([]*Movie, error) { + movies := []*Movie{} + + var polochonConfig config.UserPolochon + err := user.GetConfig("polochon", &polochonConfig) + if err != nil { + return movies, err + } + + client, err := papi.New(polochonConfig.URL, polochonConfig.Token) + if err != nil { + return movies, err + } + pmovies, err := client.MoviesByID() + if err != nil { + // Catch network error for accessing specified polochon address + if uerr, ok := err.(*url.Error); ok { + if nerr, ok := uerr.Err.(*net.OpError); ok { + if nerr.Op == "dial" { + return movies, ErrPolochonUnavailable + } + + } + } + return movies, err + } + for _, pmovie := range pmovies { + movies = append(movies, New(pmovie.ImdbID)) + } + return movies, nil +} + func FromPolochon(env *web.Env, w http.ResponseWriter, r *http.Request) error { v := auth.GetCurrentUser(r) @@ -21,21 +59,19 @@ func FromPolochon(env *web.Env, w http.ResponseWriter, r *http.Request) error { if !ok { return fmt.Errorf("invalid user type") } - var polochonConfig config.UserPolochon - err := user.GetConfig("polochon", &polochonConfig) - if err != nil { - return err - } + web.SetData(r, "user", user) + + movies, err := getPolochonMovies(user) - client, err := papi.New(polochonConfig.URL, polochonConfig.Token) if err != nil { + // Catch network error for accessing specified polochon address + if err == ErrPolochonUnavailable { + web.SetData(r, "error", "Invalid address") + return env.Rends(w, r, "movies/library") + } + return err } - pmovies, err := client.MoviesByID() - if err != nil { - return err - } - movies := []*Movie{} //TODO use configurable detailer // detailer, err := tmdb.New(&tmdb.Params{"57be344f84917b3f32c68a678f1482eb"}) @@ -44,17 +80,55 @@ func FromPolochon(env *web.Env, w http.ResponseWriter, r *http.Request) error { return err } - for _, pm := range pmovies { - m := New(pm.ImdbID) + for _, m := range movies { m.Detailers = []polochon.Detailer{detailer} err := m.GetDetails(env.Database, env.Log) if err != nil { env.Log.Error(err) } - movies = append(movies, m) } env.Log.Info(movies) return nil } + +func ExplorePopular(env *web.Env, w http.ResponseWriter, r *http.Request) error { + + queryOption := trakttv.QueryOption{ + ExtendedInfos: []trakttv.ExtendedInfo{ + trakttv.ExtendedInfoMin, + }, + Pagination: trakttv.Pagination{ + Page: 1, + Limit: 20, + }, + } + trakt := trakttv.New(env.Config.TraktTVClientID) + trakt.Endpoint = trakttv.ProductionEndpoint + tmovies, err := trakt.PopularMovies(queryOption) + if err != nil { + return err + } + + detailer, err := traktdetailer.New(&traktdetailer.Params{env.Config.TraktTVClientID}) + if err != nil { + return err + } + + movies := []*Movie{} + ids := []string{} + for _, m := range tmovies { + movie := New(m.IDs.ImDB) + movie.Detailers = []polochon.Detailer{detailer} + err := movie.GetDetails(env.Database, env.Log) + if err != nil { + env.Log.Error(err) + continue + } + movies = append(movies, movie) + ids = append(ids, m.IDs.ImDB) + } + web.SetData(r, "movies", movies) + return env.Rends(w, r, "movies/library") +} diff --git a/movies/movies.go b/movies/movies.go index 3b97216..7fa5178 100644 --- a/movies/movies.go +++ b/movies/movies.go @@ -2,11 +2,13 @@ package movies import ( "fmt" + "path/filepath" "github.com/Sirupsen/logrus" "github.com/jmoiron/sqlx" "github.com/odwrtw/polochon/lib" "gitlab.quimbo.fr/odwrtw/canape-sql/sqly" + "gitlab.quimbo.fr/odwrtw/canape-sql/web" ) const ( @@ -97,6 +99,13 @@ func (m *Movie) GetDetails(db *sqlx.DB, log *logrus.Entry) error { if err != nil { return err } + + // Download poster + err = web.Download(m.Thumb, filepath.Join("./static/img/movies", m.ImdbID+".jpg")) + if err != nil { + return err + } + return nil } diff --git a/src/js/app.js b/src/js/app.js index 650139d..db07378 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -2,3 +2,34 @@ var $ = require('jquery'); global.jQuery = global.$ = $; var bootstrap = require('bootstrap'); + +if($('#movie-library').length >0 ){ + listSelector(); +} + +// Help select elements form the list views +function listSelector() { + $first = $(".thumbnail").first(); + $first.addClass('thumbnail-selected'); + + // Get the detail + var $detail = $("#"+$first.data("imdbid")+"-detail" ); + // Show it + $detail.removeClass("hidden"); + $detail.addClass("show"); + + $(".thumbnail").click(function(e) { + e.preventDefault(); + // Hide previous details + $(".movie-detail.show" ).addClass("hidden").removeClass("show"); + + // Change border on selected item + $('.thumbnail-selected').removeClass('thumbnail-selected'); + $(this).addClass('thumbnail-selected'); + + // Get the detail + var $detail = $("#"+$(this).data("imdbid")+"-detail" ); + // Show it + $detail.removeClass("hidden").addClass("show"); + }); +} diff --git a/src/less/app.less b/src/less/app.less index b22b632..50ebdda 100644 --- a/src/less/app.less +++ b/src/less/app.less @@ -1 +1,12 @@ @import "bootstrap/less/bootstrap.less"; + +body { + padding-top: 70px; +} + +.thumbnail-selected { + border-color:#f1c40f; + background-color:#f1c40f; +} + + diff --git a/templates/layout.tmpl b/templates/layout.tmpl index 4ce3170..8d38326 100644 --- a/templates/layout.tmpl +++ b/templates/layout.tmpl @@ -10,7 +10,10 @@ + {{ template "navbar" $ }} +
{{ yield }} +
diff --git a/templates/movies/library.tmpl b/templates/movies/library.tmpl new file mode 100644 index 0000000..d31395f --- /dev/null +++ b/templates/movies/library.tmpl @@ -0,0 +1,32 @@ +{{ if $.Data.error }} + {{ if eq $.Data.error "Invalid address"}} + + {{ end }} + +{{ else }} + +
+ +
+
+ {{ range $.Data.movies }} +
+ + + +
+ {{ end }} +
+
+ +
+ {{ range $.Data.movies}} + + {{ end}} +
+ +
+ +{{ end }} diff --git a/templates/navbar.tmpl b/templates/navbar.tmpl new file mode 100644 index 0000000..e7df2e9 --- /dev/null +++ b/templates/navbar.tmpl @@ -0,0 +1,45 @@ + diff --git a/templates/users/details.tmpl b/templates/users/details.tmpl index 557b892..77aceb5 100644 --- a/templates/users/details.tmpl +++ b/templates/users/details.tmpl @@ -1,26 +1,26 @@
-
+
-
-

{{ $.Data.user.Name }}'s informations

-
+
+

{{ $.Data.user.Name }}'s informations

+
-
-
- Polochon URL -
-
{{ $.Data.polochon.URL }}
-
-
-
- Polochon token -
-
{{ $.Data.polochon.Token }}
-
+
+
+ Polochon URL +
+
{{ $.Data.polochon.URL }}
+
+
+
+ Polochon token +
+
{{ $.Data.polochon.Token }}
+
-
- Edit -
-
-
+
+ Edit +
+
+
diff --git a/users/handlers.go b/users/handlers.go index 438c178..5b1b6cd 100644 --- a/users/handlers.go +++ b/users/handlers.go @@ -12,12 +12,11 @@ import ( "gitlab.quimbo.fr/odwrtw/canape-sql/web" ) -// LoginHandler login user -func LoginHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { - if r.Method == "GET" { - return e.Rends(w, r, "users/login") - } +func LoginGETHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { + return e.Rends(w, r, "users/login") +} +func LoginPOSTHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error { type loginForm struct { Username string Password string diff --git a/web/download.go b/web/download.go new file mode 100644 index 0000000..ce84275 --- /dev/null +++ b/web/download.go @@ -0,0 +1,30 @@ +package web + +import ( + "io" + "net/http" + "os" +) + +// Download used for downloading file +var Download = func(srcURL, dest string) error { + resp, err := http.Get(srcURL) + if err != nil { + return err + } + defer resp.Body.Close() + + // Create the file + file, err := os.Create(dest) + if err != nil { + return err + } + defer file.Close() + + // Write from the net to the file + _, err = io.Copy(file, resp.Body) + if err != nil { + return err + } + return nil +} diff --git a/web/env.go b/web/env.go index 434ef2f..8b98c2a 100644 --- a/web/env.go +++ b/web/env.go @@ -4,6 +4,7 @@ import ( "fmt" "gitlab.quimbo.fr/odwrtw/canape-sql/auth" + "gitlab.quimbo.fr/odwrtw/canape-sql/config" "github.com/Sirupsen/logrus" "github.com/codegangsta/negroni" @@ -19,16 +20,27 @@ type Env struct { Router *mux.Router Render *render.Render Auth *auth.Authorizer + Config *config.Config loginRoute string } +// EnvParams represents parameters for NewEnv +type EnvParams struct { + Database *sqlx.DB + Auth *auth.Authorizer + Log *logrus.Entry + Config *config.Config + TemplatesDir string +} + // NewEnv returns a new *Env -func NewEnv(db *sqlx.DB, auth *auth.Authorizer, log *logrus.Entry, templatesDir string) *Env { +func NewEnv(p EnvParams) *Env { e := &Env{ - Database: db, - Log: log, + Database: p.Database, + Log: p.Log, Router: mux.NewRouter(), - Auth: auth, + Auth: p.Auth, + Config: p.Config, } tmplFuncs = append(tmplFuncs, map[string]interface{}{ @@ -38,7 +50,7 @@ func NewEnv(db *sqlx.DB, auth *auth.Authorizer, log *logrus.Entry, templatesDir }) e.Render = render.New(render.Options{ - Directory: templatesDir, + Directory: p.TemplatesDir, Layout: "layout", Funcs: tmplFuncs, DisableHTTPErrorRendering: true, @@ -47,17 +59,37 @@ func NewEnv(db *sqlx.DB, auth *auth.Authorizer, log *logrus.Entry, templatesDir return e } -// Handle add route -func (e *Env) Handle(name, route string, H HandlerFunc) { - e.Router.Handle(route, Handler{e, H}).Name(name) +type Route struct { + env *Env + mRoute *mux.Route } -// HandleRole add route and take care of user's role -func (e *Env) HandleRole(name, route string, H HandlerFunc, role string) { - e.Router.Handle(route, negroni.New( - auth.NewMiddlewareRole(e.Auth, e.GetLoginRouteGetter(), role), - negroni.Wrap(Handler{e, H}), - )).Name(name) +func (r *Route) Name(name string) *Route { + r.mRoute.Name(name) + return r +} + +func (r *Route) Methods(methods ...string) *Route { + r.mRoute.Methods(methods...) + return r +} + +func (r *Route) WithRole(role string) *Route { + handler := r.mRoute.GetHandler() + newHandler := negroni.New( + auth.NewMiddlewareRole(r.env.Auth, r.env.GetLoginRouteGetter(), role), + negroni.Wrap(handler)) + r.mRoute.Handler(newHandler) + return r +} + +// Handle add route +func (e *Env) Handle(route string, H HandlerFunc) *Route { + mRoute := e.Router.Handle(route, Handler{e, H}) + return &Route{ + env: e, + mRoute: mRoute, + } } // GetURL returns URL string from URL name and params diff --git a/web/templates.go b/web/templates.go index 1b494da..6c8e41c 100644 --- a/web/templates.go +++ b/web/templates.go @@ -26,21 +26,21 @@ func AddTmplFunc(name string, f interface{}) error { // TemplateData represents object passed to template renderer type TemplateData struct { - RouteName string - Data map[string]interface{} + Route string + Data map[string]interface{} } // Rends a view func (e *Env) Rends(w http.ResponseWriter, r *http.Request, template string) error { if r.Header.Get("Accept") == "application/json" { return e.Render.JSON(w, http.StatusOK, TemplateData{ - RouteName: mux.CurrentRoute(r).GetName(), - Data: GetAllData(r), + Route: mux.CurrentRoute(r).GetName(), + Data: GetAllData(r), }) } return e.Render.HTML(w, http.StatusOK, template, TemplateData{ - RouteName: mux.CurrentRoute(r).GetName(), - Data: GetAllData(r), + Route: mux.CurrentRoute(r).GetName(), + Data: GetAllData(r), }) }