diff options
Diffstat (limited to 'src/dbx/users.go')
-rw-r--r-- | src/dbx/users.go | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/dbx/users.go b/src/dbx/users.go new file mode 100644 index 0000000..e2270db --- /dev/null +++ b/src/dbx/users.go @@ -0,0 +1,68 @@ +package dbx + +import ( + "database/sql" + "errors" + + "golang.org/x/crypto/bcrypt" + "golang.org/x/text/unicode/norm" +) + +type User struct { + Email string `db:"email"` + Username string `db:"username"` + Password string `db:"password"` + AdminP bool `db:"adminp"` + Translates string `db:"translates"` +} + +var LoginFailed = errors.New("No user with the given username and password") + +func CreateUser(user User) error { + user.Username = norm.NFC.String(user.Username) + user.Password = norm.NFC.String(user.Password) + + hash, err := bcrypt.GenerateFromPassword([]byte(user.Password), 15) + if err != nil { + return err + } + + _, err = db.Exec(` + INSERT INTO users ( + email, + username, + password, + adminp, + translates + ) VALUES (?, ?, ?, ?, ?) + `, user.Email, user.Username, string(hash), user.AdminP, user.Translates) + return err +} + +func Login(username, password string) (User, error) { + username = norm.NFC.String(username) + password = norm.NFC.String(password) + + /* TODO: Pass a context here? */ + rs, err := db.Query(`SELECT * FROM users WHERE username = ?`, username) + if err != nil { + return User{}, err + } + u, err := scanToStruct[User](rs) + + switch { + case errors.Is(err, sql.ErrNoRows): + return User{}, LoginFailed + case err != nil: + return User{}, err + } + + err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) + switch { + case errors.Is(err, bcrypt.ErrMismatchedHashAndPassword): + return User{}, LoginFailed + case err != nil: + return User{}, err + } + return u, nil +} |