Created
June 3, 2022 06:47
-
-
Save gocs/8ee81749694224098a286bf6690523b1 to your computer and use it in GitHub Desktop.
simple auth web app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package auth | |
import ( | |
"errors" | |
"html/template" | |
"log" | |
"net/http" | |
"time" | |
"github.com/go-chi/jwtauth/v5" | |
) | |
// AuthController is a pluggable controller with handlers only for authenticating users | |
// This has its own login/logout form template, so long as it contains these endpoints: | |
// "/logout" | |
// "/login" | |
// "/signup" | |
// "/auth" | |
// This requires jwt in the cookies | |
// you can implement your own UserVerify and SignUp methods | |
// you can provide your own redirection URLs | |
type AuthController struct { | |
username string | |
loginErr error | |
tokenAuth *jwtauth.JWTAuth | |
loginURL string | |
logoutURL string | |
SignUpURL string | |
} | |
func (ac *AuthController) Verifier() func(http.Handler) http.Handler { | |
return jwtauth.Verifier(ac.tokenAuth) | |
} | |
func New(secret []byte) (*AuthController, error) { | |
return &AuthController{ | |
tokenAuth: jwtauth.New("HS256", secret, nil), | |
loginURL: "/login", | |
logoutURL: "/logout", | |
SignUpURL: "/signup", | |
}, nil | |
} | |
func (ac *AuthController) GetUsername() string { | |
return ac.username | |
} | |
type UserVerifier interface { | |
UserVerify(username string, password []byte) error | |
} | |
func (ac *AuthController) Login(uv UserVerifier, redirectURL string) http.HandlerFunc { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
// verify username and password | |
if r.FormValue("Login") == "" && r.FormValue("Username") == "" { | |
if ac.username == "" { | |
ac.loginErr = errors.New("user not logged in") | |
} else { | |
log.Println("Logged in:", ac.username) | |
} | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
return | |
} | |
username := r.FormValue("Username") | |
password := r.FormValue("Password") | |
if err := uv.UserVerify(username, []byte(password)); err != nil { | |
log.Println("user verify err:", err) | |
ac.loginErr = errors.New("either username or password is wrong") | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
return | |
} | |
// create a new JSON Web Token and redirect to dashboard | |
_, tokenString, err := ac.tokenAuth.Encode(map[string]any{"username": username}) | |
if err != nil { | |
log.Println("cannot generate token:", err) // of course, this is too simple, your program should prevent login if token cannot be generated!! | |
return | |
} | |
// create the cookie for client(browser) | |
http.SetCookie(w, &http.Cookie{ | |
Name: "jwt", // TokenFromCookie | |
Value: tokenString, | |
Expires: time.Now().Add(2 * time.Minute), // cookie expired after 1 hour, | |
}) | |
ac.username = username | |
ac.loginErr = nil | |
log.Println("Logged in:", ac.username) | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
}) | |
} | |
func (ac *AuthController) Logout(redirectURL string) http.HandlerFunc { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
http.SetCookie(w, &http.Cookie{Name: "jwt", MaxAge: -1}) // TokenFromCookie | |
ac.loginErr = nil | |
ac.username = "" | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
}) | |
} | |
func (ac *AuthController) Form(tmpl *template.Template) http.HandlerFunc { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
tmplVars := map[string]any{} | |
if ac.loginErr != nil { | |
tmplVars["LoginError"] = true | |
} | |
tmplVars["Username"] = ac.username | |
tmplVars["LogoutURL"] = ac.logoutURL | |
tmplVars["LoginURL"] = ac.loginURL | |
tmplVars["SignUpURL"] = ac.SignUpURL | |
if err := tmpl.Execute(w, tmplVars); err != nil { | |
log.Println(err) | |
} | |
}) | |
} | |
type SignUper interface { | |
SignUp(username string, password []byte) error | |
} | |
func (ac *AuthController) SignUp(su SignUper, redirectURL string) http.HandlerFunc { | |
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
if r.FormValue("Login") == "" && r.FormValue("Username") == "" { | |
if ac.username == "" { | |
ac.loginErr = errors.New("user not logged in") | |
} else { | |
log.Println("Logged in:", ac.username) | |
} | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
return | |
} | |
username := r.FormValue("Username") | |
password := r.FormValue("Password") | |
if err := su.SignUp(username, []byte(password)); err != nil { | |
log.Println("user verify err:", err) | |
ac.loginErr = errors.New("either username or password is wrong") | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
return | |
} | |
http.Redirect(w, r, redirectURL, http.StatusFound) | |
}) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"logio/controller" | |
) | |
// used to encrypt/decrypt JWT tokens. Change it to yours. | |
var jwtTokenSecret = "wwwwwfwfwfwfqwfqwfqwfxx123123@@@#!@#!shit" | |
func main() { | |
c, err := controller.New("users.db", jwtTokenSecret) | |
if err != nil { | |
log.Fatalln("controller error:", err) | |
} | |
log.Println("Server starting, point your browser to localhost:8080/auth to start") | |
log.Fatal(c.Serve(":8080")) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controller | |
import ( | |
"fmt" | |
"html/template" | |
"logio/auth" | |
"logio/store" | |
"net/http" | |
"github.com/go-chi/chi/v5" | |
"github.com/go-chi/jwtauth/v5" | |
) | |
type Controller struct { | |
r *chi.Mux | |
s *store.Store | |
jwtTokenSecret []byte | |
} | |
func New(filename, jwtTokenSecret string) (*Controller, error) { | |
r := chi.NewRouter() | |
s, err := store.New(filename) | |
if err != nil { | |
return nil, err | |
} | |
return &Controller{ | |
r: r, | |
s: s, | |
jwtTokenSecret: []byte(jwtTokenSecret), | |
}, nil | |
} | |
var authformTemplate = template.Must(template.New("").Parse(` | |
<html> | |
<body> | |
{{if .Username}} | |
<p><b>{{.Username}}</b>, welcome to your dashboard! <a href="{{.LogoutURL}}">Logout!</a></p> | |
{{else}} | |
<form method="POST" action="{{.LoginURL}}"> | |
<label>Username:</label> | |
<input type="text" name="Username"><br> | |
<label>Password:</label> | |
<input type="password" name="Password"> | |
{{if .LoginError}} | |
<span style="font-style:italic; color:red"> | |
Either username or password is not in our record! | |
<a href="{{.SignUpURL}}"> | |
Sign Up? | |
</a> | |
</span><br> | |
{{end}} | |
<input type="submit" name="Login" value="submit"> | |
</form> | |
{{end}} | |
</body> | |
</html>`)) | |
func (c *Controller) Serve(addr string) error { | |
ac, _ := auth.New(c.jwtTokenSecret) | |
c.r.Post("/signup", ac.SignUp(c.s, "/auth")) | |
c.r.Post("/login", ac.Login(c.s, "/auth")) | |
c.r.Get("/logout", ac.Logout("/auth")) | |
c.r.Get("/auth", ac.Form(authformTemplate)) | |
c.r.Group(func(r chi.Router) { | |
r.Use(ac.Verifier()) | |
r.Use(jwtauth.Authenticator) | |
r.Get("/admin", func(w http.ResponseWriter, r *http.Request) { | |
_, claims, _ := jwtauth.FromContext(r.Context()) | |
w.Write([]byte(fmt.Sprintf("protected area. hi %v", claims["username"]))) | |
}) | |
}) | |
defer c.s.Close() | |
return http.ListenAndServe(addr, c.r) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module logio | |
go 1.18 | |
require ( | |
github.com/go-chi/chi/v5 v5.0.7 | |
github.com/go-chi/jwtauth/v5 v5.0.2 | |
go.etcd.io/bbolt v1.3.6 | |
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e | |
) | |
require ( | |
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d // indirect | |
github.com/goccy/go-json v0.7.6 // indirect | |
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect | |
github.com/lestrrat-go/blackmagic v1.0.0 // indirect | |
github.com/lestrrat-go/httpcc v1.0.0 // indirect | |
github.com/lestrrat-go/iter v1.0.1 // indirect | |
github.com/lestrrat-go/jwx v1.2.6 // indirect | |
github.com/lestrrat-go/option v1.0.0 // indirect | |
github.com/pkg/errors v0.9.1 // indirect | |
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | |
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= | |
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d h1:1iy2qD6JEhHKKhUOA9IWs7mjco7lnw2qx8FsRI2wirE= | |
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE= | |
github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= | |
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= | |
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= | |
github.com/go-chi/jwtauth/v5 v5.0.2 h1:CSKtr+b6Jnfy5T27sMaiBPxaVE/bjnjS3ramFQ0526w= | |
github.com/go-chi/jwtauth/v5 v5.0.2/go.mod h1:TeA7vmPe3uYThvHw8O8W13HOOpOd4MTgToxL41gZyjs= | |
github.com/goccy/go-json v0.7.6 h1:H0wq4jppBQ+9222sk5+hPLL25abZQiRuQ6YPnjO9c+A= | |
github.com/goccy/go-json v0.7.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | |
github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= | |
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= | |
github.com/lestrrat-go/blackmagic v1.0.0 h1:XzdxDbuQTz0RZZEmdU7cnQxUtFUzgCSPq8RCz4BxIi4= | |
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ= | |
github.com/lestrrat-go/codegen v1.0.1/go.mod h1:JhJw6OQAuPEfVKUCLItpaVLumDGWQznd1VaXrBk9TdM= | |
github.com/lestrrat-go/httpcc v1.0.0 h1:FszVC6cKfDvBKcJv646+lkh4GydQg2Z29scgUfkOpYc= | |
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE= | |
github.com/lestrrat-go/iter v1.0.1 h1:q8faalr2dY6o8bV45uwrxq12bRa1ezKrB6oM9FUgN4A= | |
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= | |
github.com/lestrrat-go/jwx v1.2.6 h1:XAgfuHaOB7fDZ/6WhVgl8K89af768dU+3Nx4DlTbLIk= | |
github.com/lestrrat-go/jwx v1.2.6/go.mod h1:tJuGuAI3LC71IicTx82Mz1n3w9woAs2bYJZpkjJQ5aU= | |
github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= | |
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= | |
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | |
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | |
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | |
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= | |
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= | |
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | |
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= | |
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | |
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | |
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= | |
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | |
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= | |
golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package store | |
import ( | |
"fmt" | |
bolt "go.etcd.io/bbolt" | |
"golang.org/x/crypto/bcrypt" | |
) | |
type User struct { | |
ID []byte | |
Username string | |
Password []byte | |
} | |
type Store struct { | |
db *bolt.DB | |
bucketName string | |
} | |
func (s *Store) Close() { | |
s.db.Close() | |
} | |
func New(filename string) (*Store, error) { | |
db, err := bolt.Open(filename, 0644, nil) | |
if err != nil { | |
return nil, err | |
} | |
tx, err := db.Begin(true) | |
if err != nil { | |
return nil, err | |
} | |
defer tx.Rollback() | |
if b := tx.Bucket([]byte(filename)); b == nil { | |
if _, err := tx.CreateBucket([]byte(filename)); err != nil { | |
return nil, err | |
} | |
} | |
if err := tx.Commit(); err != nil { | |
return nil, err | |
} | |
return &Store{ | |
db: db, | |
bucketName: filename, | |
}, nil | |
} | |
func (s *Store) SignUp(username string, password []byte) error { | |
return s.db.Update(func(tx *bolt.Tx) error { | |
b := tx.Bucket([]byte(s.bucketName)) | |
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost) | |
if err != nil { | |
return err | |
} | |
return b.Put([]byte(username), hashedPassword) | |
}) | |
} | |
func (s *Store) UserVerify(username string, password []byte) error { | |
return s.db.Update(func(tx *bolt.Tx) error { | |
b := tx.Bucket([]byte(s.bucketName)) | |
p := b.Get([]byte(username)) | |
return bcrypt.CompareHashAndPassword(p, password) | |
}) | |
} | |
func (s *Store) GetAll() error { | |
return s.db.View(func(tx *bolt.Tx) error { | |
b := tx.Bucket([]byte(s.bucketName)) | |
b.ForEach(func(k, v []byte) error { | |
fmt.Printf("key=%s, value=%s\n", k, v) | |
return nil | |
}) | |
return nil | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment