From b3c1584ec4a5bcba84a10cd9b6501d0e978c2457 Mon Sep 17 00:00:00 2001 From: Alexander Kavon Date: Mon, 22 Jan 2024 00:37:21 -0500 Subject: update db adapter, server, routes, and user model to be sqlboiler compatible --- src/user/routes.go | 26 +++++++++--------- src/user/secret.go | 55 ++++++++++++++++++++++++++++++++++++++ src/user/user.go | 78 ------------------------------------------------------ 3 files changed, 69 insertions(+), 90 deletions(-) create mode 100644 src/user/secret.go delete mode 100644 src/user/user.go (limited to 'src/user') diff --git a/src/user/routes.go b/src/user/routes.go index d8c8d43..b163fb7 100644 --- a/src/user/routes.go +++ b/src/user/routes.go @@ -5,6 +5,8 @@ import ( "net/http" "github.com/go-playground/validator/v10" + "github.com/volatiletech/sqlboiler/v4/boil" + "gitlab.com/alexkavon/newsstand/src/models" "gitlab.com/alexkavon/newsstand/src/server" "gitlab.com/alexkavon/newsstand/src/sessions" ) @@ -64,33 +66,33 @@ func Store(s *server.Server) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { r.ParseForm() - user := &User{ - Db: s.Db, - Username: r.PostFormValue("username"), - Secret: r.PostFormValue("secret"), - Email: r.PostFormValue("email"), - } + var user models.User + user.Username = r.PostFormValue("username") + user.Secret = r.PostFormValue("secret") + user.Email = r.PostFormValue("email") // Validate User Input v := validator.New() err := v.Struct(user) if err != nil { - log.Println("Validator failed", err.(validator.ValidationErrors)) + log.Fatal("Validator failed", err.(validator.ValidationErrors)) } // Hash secret - err = user.HashSecret() + secret := &Secret{Raw: user.Secret} + err = secret.HashSecret() if err != nil { - log.Println("Hash failure", err) + log.Fatal("Hash failure", err) } + user.Secret = secret.Hash() // Store user - err = user.Insert() + err = user.Insert(r.Context(), s.Db.ToSqlDb(), boil.Infer()) if err != nil { - log.Println("Insert Error", err) + log.Fatal("Insert Error", err) } // Send email validation // Create cookie session - sessions.NewSession(w, sessions.SessionValues{"uid": user.Id, "username": user.Username}) + sessions.NewSession(w, sessions.SessionValues{"uid": user.ID, "username": user.Username}) // Redirect to user profile http.Redirect(w, r, "/u/me", http.StatusSeeOther) } diff --git a/src/user/secret.go b/src/user/secret.go new file mode 100644 index 0000000..55b8bc6 --- /dev/null +++ b/src/user/secret.go @@ -0,0 +1,55 @@ +package user + +import ( + "crypto/rand" + "encoding/base64" + "fmt" + + "golang.org/x/crypto/argon2" +) + +type Secret struct { + Raw string + hash string +} + +func (s Secret) HashSecret() error { + hashconf := &struct { + memory uint32 + iterations uint32 + parallelism uint8 + keyLength uint32 + saltLength uint32 + }{64 * 1024, 3, 2, 12, 16} + salt := make([]byte, hashconf.saltLength) + _, err := rand.Read(salt) + if err != nil { + return err + } + + hash := argon2.IDKey( + []byte(s.Raw), + salt, + hashconf.iterations, + hashconf.memory, + hashconf.parallelism, + hashconf.keyLength, + ) + b64Salt := base64.RawStdEncoding.EncodeToString(salt) + b64Hash := base64.RawStdEncoding.EncodeToString(hash) + encodedHash := fmt.Sprintf( + "$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", + argon2.Version, + hashconf.memory, + hashconf.iterations, + hashconf.parallelism, + b64Salt, + b64Hash, + ) + s.hash = encodedHash + return err +} + +func (s *Secret) Hash() string { + return s.hash +} diff --git a/src/user/user.go b/src/user/user.go deleted file mode 100644 index d9fca6b..0000000 --- a/src/user/user.go +++ /dev/null @@ -1,78 +0,0 @@ -package user - -import ( - "crypto/rand" - "encoding/base64" - "fmt" - "time" - - "gitlab.com/alexkavon/newsstand/src/db" - "golang.org/x/crypto/argon2" -) - -type User struct { - Id int64 - Username string `validate:"required,max=50"` - Secret string `validate:"required,min=8,max=128"` - Email string `validate:"required,email"` - Karma uint64 - UpdatedAt time.Time - CreatedAt time.Time - hash string - Db *db.Database -} - -func NewUser(d *db.Database) *User { - return &User{ - Db: d, - } -} - -func (u *User) Insert() error { - err := u.Db.InsertTable( - "users", - []string{"username", "secret", "email"}, - db.DbValues{"username": u.Username, "secret": string(u.hash), "email": u.Email}, - ) - if err != nil { - return err - } - return nil -} - -func (u *User) HashSecret() error { - hashconf := &struct { - memory uint32 - iterations uint32 - parallelism uint8 - keyLength uint32 - saltLength uint32 - }{64 * 1024, 3, 2, 12, 16} - salt := make([]byte, hashconf.saltLength) - _, err := rand.Read(salt) - if err != nil { - return err - } - - hash := argon2.IDKey( - []byte(u.Secret), - salt, - hashconf.iterations, - hashconf.memory, - hashconf.parallelism, - hashconf.keyLength, - ) - b64Salt := base64.RawStdEncoding.EncodeToString(salt) - b64Hash := base64.RawStdEncoding.EncodeToString(hash) - encodedHash := fmt.Sprintf( - "$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", - argon2.Version, - hashconf.memory, - hashconf.iterations, - hashconf.parallelism, - b64Salt, - b64Hash, - ) - u.hash = encodedHash - return nil -} -- cgit v1.2.3