package db import ( "errors" "time" pgsql "github.com/fergusstrange/embedded-postgres" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" "github.com/rs/zerolog/log" ) var ( db *sqlx.DB postgres *pgsql.EmbeddedPostgres ) // User represents a mapy user. type User struct { ID int64 `db:"id"` Username string `db:"username"` Password string `db:"password"` Creation time.Time `db:"creation"` LastLogin time.Time `db:"last_login"` LastIP string `db:"last_ip"` Ban int `db:"ban"` Admin int `db:"admin"` Gender int `db:"gender"` } func getUser(username string) (u *User, err error) { u = new(User) if err = db.Get(u, "SELECT * FROM accounts WHERE username=$1", username); err != nil { return nil, err } return u, nil } // UserExists queries our database for a user using the given username and returns true if it exists, false if it does not. func UserExists(username string) bool { u := new(User) if err := db.Get(u, "SELECT id FROM accounts WHERE username=$1", username); err != nil { return false } return true } // EmailTaken queries our database for a user using the given email address and returns true if the email is taken, false if it is not. func EmailTaken(email string) bool { u := new(User) if err := db.Get(u, "SELECT id FROM accounts WHERE email=$1", email); err == nil { return true } return false } // AttemptWebLogin checks the given credentials for validity and returns a User and an error. func AttemptWebLogin(username, password, ipaddr, useragent string) (*User, error) { var ( u *User err error good = false ) defer func() { // TODO: make bitcask max value size larger because this 000 is gonna get huge // to log invalid users if u == nil { u = &User{ID: 000} } if err := authlog.newAttempt(int(u.ID), ipaddr, useragent, Web, good); err != nil { println(err.Error()) log.Error().Err(err).Msg("failed_login") } }() if u, err = getUser(username); err != nil { return u, err } if !CheckPasswordHash(password, u.Password) { return nil, errors.New("invalid password") } good = true return u, nil } // RegisterNewUser registers a new mapyweb user func RegisterNewUser(username, password, ipaddr string, gender int, admin bool) error { hashed, err := HashPassword(password) if err != nil { return err } if !CheckPasswordHash(password, hashed) { return errors.New("FAILED PASSWORD HASHING") } u := &User{ Username: username, Password: hashed, Creation: time.Now(), LastLogin: time.Now(), LastIP: ipaddr, Ban: 0, Gender: gender, } if admin { u.Admin = 1 } else { u.Admin = 0 } _, err = db.NamedExec(`INSERT INTO accounts (username, password, creation, last_login, last_ip, ban, admin, gender) VALUES (:username, :password, :creation, :last_login, :last_ip, 0, :admin, :gender);`, u) return err }