website/pkg/models/user.go

87 lines
2.2 KiB
Go

package models
import (
"errors"
"strings"
"time"
"git.kirsle.net/apps/gosocial/pkg/config"
"golang.org/x/crypto/bcrypt"
)
// User account table.
type User struct {
ID uint64 `gorm:"primaryKey`
Username string `gorm:"uniqueIndex"`
Email string `gorm:"uniqueIndex"`
HashedPassword string
IsAdmin bool `gorm:"index"`
Status string `gorm:"index"` // pending, active, disabled
Visibility string `gorm:"index"` // public, private
Name *string
Certified bool
CreatedAt time.Time `gorm:"index"`
UpdatedAt time.Time `gorm:"index"`
}
// CreateUser. It is assumed username and email are correctly formatted.
func CreateUser(username, email, password string) (*User, error) {
// Verify username and email are unique.
if _, err := FindUser(username); err == nil {
return nil, errors.New("That username already exists. Please try a different username.")
} else if _, err := FindUser(email); err == nil {
return nil, errors.New("That email address is already registered.")
}
u := &User{
Username: username,
Email: email,
}
if err := u.HashPassword(password); err != nil {
return nil, err
}
result := DB.Create(u)
return u, result.Error
}
// GetUser by ID.
func GetUser(userId uint64) (*User, error) {
user := &User{}
result := DB.First(&user, userId)
return user, result.Error
}
// FindUser by username or email.
func FindUser(username string) (*User, error) {
u := &User{}
if strings.ContainsRune(username, '@') {
result := DB.Where("email = ?", username).Limit(1).First(u)
return u, result.Error
}
result := DB.Where("username = ?", username).Limit(1).First(u)
return u, result.Error
}
// HashPassword sets the user's hashed (bcrypt) password.
func (u *User) HashPassword(password string) error {
passwd, err := bcrypt.GenerateFromPassword([]byte(password), config.BcryptCost)
if err != nil {
return err
}
u.HashedPassword = string(passwd)
return nil
}
// CheckPassword verifies the password is correct. Returns nil on success.
func (u *User) CheckPassword(password string) error {
return bcrypt.CompareHashAndPassword([]byte(u.HashedPassword), []byte(password))
}
// Save user.
func (u *User) Save() error {
result := DB.Save(u)
return result.Error
}