aboutsummaryrefslogtreecommitdiff
path: root/src/user/hooks.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/hooks.go')
-rw-r--r--src/user/hooks.go72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/user/hooks.go b/src/user/hooks.go
new file mode 100644
index 0000000..0ab5ab0
--- /dev/null
+++ b/src/user/hooks.go
@@ -0,0 +1,72 @@
+package user
+
+import (
+ "context"
+ "crypto/rand"
+ "encoding/base64"
+ "fmt"
+
+ validation "github.com/go-ozzo/ozzo-validation/v4"
+ "github.com/go-ozzo/ozzo-validation/v4/is"
+ "github.com/volatiletech/sqlboiler/v4/boil"
+ "gitlab.com/alexkavon/newsstand/src/models"
+ "golang.org/x/crypto/argon2"
+)
+
+func init() {
+ models.AddUserHook(boil.BeforeInsertHook, validate)
+ // should always be last
+ models.AddUserHook(boil.BeforeInsertHook, hashSecret)
+}
+
+func validate(ctx context.Context, exec boil.ContextExecutor, u *models.User) error {
+ // validate user
+ err := validation.ValidateStruct(u,
+ validation.Field(&u.Username, validation.Required, validation.Length(3, 50)),
+ validation.Field(&u.Secret, validation.Required, validation.Length(8, 128)),
+ validation.Field(&u.Email, validation.Required, is.Email),
+ )
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func hashSecret(ctx context.Context, exec boil.ContextExecutor, u *models.User) 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.Secret = encodedHash
+ return nil
+}