diff --git a/main.go b/main.go index 38dfadc..49fc356 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "crypto/tls" "embed" + "git.keks.cloud/kekskurse/go-sample-webpage/pkg/dashboard" "git.keks.cloud/kekskurse/go-sample-webpage/pkg/sample" "git.keks.cloud/kekskurse/go-sample-webpage/pkg/user" "git.keks.cloud/kekskurse/go-sample-webpage/pkg/webpage" @@ -21,12 +22,13 @@ var webserver embed.FS var migrationFS embed.FS func main() { + tokenAuth := jwtauth.New("HS256", []byte("secret"), nil) config := webpage.WebPageConfig{ Templates: webserver, Static: webserver, Migrations: migrationFS, + Token: tokenAuth, Bootstrap: func(router chi.Router, template func(http.Handler) http.Handler) { - tokenAuth := jwtauth.New("HS256", []byte("secret"), nil) db, err := sqlx.Open("mysql", "root:test@tcp(localhost:3306)/test?multiStatements=true") if err != nil { panic(err) @@ -40,6 +42,8 @@ func main() { sample.Register(router) user.Register(router, template, tokenAuth, uc, d, userconfig) + + dashboard.Register(router, template) }, } diff --git a/pkg/dashboard/dashboard.go b/pkg/dashboard/dashboard.go new file mode 100644 index 0000000..ed539ef --- /dev/null +++ b/pkg/dashboard/dashboard.go @@ -0,0 +1,32 @@ +package dashboard + +import ( + "embed" + "github.com/go-chi/chi/v5" + "github.com/unrolled/render" + "net/http" +) + +// content holds our static web server content. +//go:embed templates/* +var webserver embed.FS + +var ren *render.Render + +func Register(router chi.Router, template func(http.Handler) http.Handler) { + ren = render.New(render.Options{ + //Layout: "layout", + FileSystem: &render.EmbedFileSystem{ + FS: webserver, + }, + }) + + router.Group(func(r chi.Router) { + r.Use(template) + r.Get("/dashboard", sampleCall) + }) +} + +func sampleCall(w http.ResponseWriter, r *http.Request) { + ren.HTML(w, http.StatusOK, "dashboard", map[string]string {"title": "World"}) +} \ No newline at end of file diff --git a/pkg/sample/templates/ssp.tmpl b/pkg/dashboard/templates/dashboard.tmpl similarity index 100% rename from pkg/sample/templates/ssp.tmpl rename to pkg/dashboard/templates/dashboard.tmpl diff --git a/pkg/sample/sample.go b/pkg/sample/sample.go index 8f9de6e..e30f7f8 100644 --- a/pkg/sample/sample.go +++ b/pkg/sample/sample.go @@ -25,5 +25,5 @@ func Register(router chi.Router) { } func sampleCall(w http.ResponseWriter, r *http.Request) { - ren.HTML(w, http.StatusOK, "ssp", map[string]string {"title": "World"}) + ren.HTML(w, http.StatusOK, "dashboard", map[string]string {"title": "World"}) } \ No newline at end of file diff --git a/pkg/sample/templates/dashboard.tmpl b/pkg/sample/templates/dashboard.tmpl new file mode 100644 index 0000000..ef82d43 --- /dev/null +++ b/pkg/sample/templates/dashboard.tmpl @@ -0,0 +1 @@ +BLABLA Something \ No newline at end of file diff --git a/pkg/user/user.go b/pkg/user/user.go index 4fdb119..4c0a78d 100644 --- a/pkg/user/user.go +++ b/pkg/user/user.go @@ -70,6 +70,7 @@ func Register(router chi.Router, template func(http.Handler) http.Handler, token r.Get("/register", registerForm) r.Post("/register", register) r.Get("/logout", logout) + r.Get("/validate/{mail}/{token}", validateMail) }) router.Get("/captcha/{id}.png", captchaImage) @@ -95,6 +96,27 @@ func Register(router chi.Router, template func(http.Handler) http.Handler, token } +func validateMail(w http.ResponseWriter, r *http.Request) { + mailinput := chi.URLParam(r, "mail") + token := chi.URLParam(r, "token") + + mailbytes, _ := base64.StdEncoding.DecodeString(mailinput) + mail := string(mailbytes) + + res, err := uc.validateMail(mail, token) + + if err != nil { + panic(err) + } + + if res == false{ + w.Write([]byte("Invalide or alrady used link")) + return + } + + w.Write([]byte("Account is activated, you can login now")) +} + func captchaImage(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") w.Header().Set("Content-Type", "image/png") @@ -132,6 +154,7 @@ func login(w http.ResponseWriter, r *http.Request) { expiration := time.Now().Add(365 * 24 * time.Hour) cookie := http.Cookie{Name: "jwt",Value:tokenstring,Expires:expiration} http.SetCookie(w, &cookie) + http.Redirect(w, r, "/dashboard", 301) w.Write([]byte("Login ok")) } else { w.Write([]byte("Login failed")) diff --git a/pkg/user/userclient.go b/pkg/user/userclient.go index 2a25112..a98acd8 100644 --- a/pkg/user/userclient.go +++ b/pkg/user/userclient.go @@ -14,6 +14,7 @@ type UserClient interface { register(username, password, email string) (bool, error) login(username, password string, requiredMailValidation bool) (bool, error) getMailValidationToken(email string, forceRecreate bool) (string, error) + validateMail(email, token string) (bool, error) } type UserClientMemory struct { @@ -26,6 +27,9 @@ func GetUserMemmoryClient() *UserClientMemory { uc.users["admin"]="password" return &uc } +func (uc *UserClientMemory) validateMail(email, token string) (bool, error) { + return true, nil +} func (uc *UserClientMemory) register(username, password, email string) (bool, error) { if _, ok := uc.users[username]; ok { @@ -130,6 +134,25 @@ func (uc UserClientSql) getMailValidationToken(email string, forceRecreate bool) //token = fmt.Sprintf("%v/%v", base64.StdEncoding.EncodeToString([]byte(email)), token) return token, nil } +func (uc *UserClientSql) validateMail(email, token string) (bool, error) { + user := User{} + err := uc.db.Get(&user, "SELECT * FROM `user` WHERE `mail` = ?", email) + if err != nil { + return false, err + } + + if user.MailValidationCode != nil && *user.MailValidationCode == token { + _, err = uc.db.NamedExec("UPDATE `user` SET `mailValidationCode` = NULL, `mailValidate` = 1 WHERE id = :id LIMIT 1", map[string]interface{}{ + "id": user.Id, + }) + if err != nil { + return false, err + } + return true, nil + } + return false, nil +} + func (uc UserClientSql)hashAndSalt(pwd []byte) string { diff --git a/pkg/webpage/layoutmiddleware.go b/pkg/webpage/layoutmiddleware.go index 7f36a64..85d61e5 100644 --- a/pkg/webpage/layoutmiddleware.go +++ b/pkg/webpage/layoutmiddleware.go @@ -2,6 +2,7 @@ package webpage import ( "bytes" + "github.com/go-chi/jwtauth/v5" "github.com/unrolled/render" "html/template" "io" @@ -41,6 +42,15 @@ func TemplateMiddelware(next http.Handler) http.Handler { } rw.buf.Reset() - render.HTML(w, http.StatusOK, "sub", template.HTML(string(content))) + + + _, claims, _ := jwtauth.FromContext(r.Context()) + + loggedin := false + if claims["username"] != nil { + loggedin = true + } + + render.HTML(w, http.StatusOK, "sub", map[string]interface{}{"loggedin": loggedin, "content": template.HTML(string(content))}) }) } \ No newline at end of file diff --git a/pkg/webpage/webpage.go b/pkg/webpage/webpage.go index 412a055..6826292 100644 --- a/pkg/webpage/webpage.go +++ b/pkg/webpage/webpage.go @@ -5,6 +5,7 @@ import ( "embed" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" + "github.com/go-chi/jwtauth/v5" "github.com/golang-migrate/migrate/v4" "github.com/golang-migrate/migrate/v4/database/mysql" "github.com/golang-migrate/migrate/v4/source/iofs" @@ -20,6 +21,7 @@ type WebPageConfig struct { Templates embed.FS Static embed.FS Migrations embed.FS + Token *jwtauth.JWTAuth Bootstrap func(router chi.Router, middlewares func(http.Handler) http.Handler) } @@ -67,6 +69,8 @@ func runWebpage() error { }, }) r.Use(middleware.Logger) + r.Use(jwtauth.Verifier(config.Token)) + r.Handle("/static/*", http.FileServer(http.FS(config.Static))) r.Group(func(r chi.Router) { diff --git a/templates/layout.tmpl b/templates/layout.tmpl index 6283df8..b8d8b92 100644 --- a/templates/layout.tmpl +++ b/templates/layout.tmpl @@ -44,16 +44,23 @@
diff --git a/templates/sub.tmpl b/templates/sub.tmpl index 666839a..5718d38 100644 --- a/templates/sub.tmpl +++ b/templates/sub.tmpl @@ -1 +1 @@ -{{ . }} \ No newline at end of file +{{ .content }} \ No newline at end of file diff --git a/vendor/github.com/dchest/captcha/captcha.go b/vendor/github.com/dchest/captcha/captcha.go index 158ea9e..33f6c0d 100644 --- a/vendor/github.com/dchest/captcha/captcha.go +++ b/vendor/github.com/dchest/captcha/captcha.go @@ -50,7 +50,6 @@ import ( "errors" "io" "time" - "fmt" ) const ( @@ -137,7 +136,6 @@ func Verify(id string, digits []byte) bool { return false } reald := globalStore.Get(id, true) - fmt.Println(reald) if reald == nil { return false }