This commit is contained in:
parent
508f7bf4b7
commit
360ee1c5fe
12 changed files with 110 additions and 8 deletions
6
main.go
6
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)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
32
pkg/dashboard/dashboard.go
Normal file
32
pkg/dashboard/dashboard.go
Normal file
|
@ -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"})
|
||||
}
|
|
@ -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"})
|
||||
}
|
1
pkg/sample/templates/dashboard.tmpl
Normal file
1
pkg/sample/templates/dashboard.tmpl
Normal file
|
@ -0,0 +1 @@
|
|||
BLABLA <b>Something</b>
|
|
@ -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"))
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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))})
|
||||
})
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -44,16 +44,23 @@
|
|||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav me-auto">
|
||||
{{if .loggedin }}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Account</a>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="/login">Login</a>
|
||||
<a class="dropdown-item" href="/register">Register</a>
|
||||
<a class="dropdown-item" href="/me">Me</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="/logout">Logout</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ else }}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/register">Register</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/login">Login</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -1 +1 @@
|
|||
{{ . }}
|
||||
{{ .content }}
|
2
vendor/github.com/dchest/captcha/captcha.go
generated
vendored
2
vendor/github.com/dchest/captcha/captcha.go
generated
vendored
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue