This repository has been archived on 2025-03-30. You can view files and clone it, but cannot push or open issues or pull requests.
bactdb/users.go
2015-04-22 17:03:45 -08:00

133 lines
3.2 KiB
Go

package main
import (
"database/sql"
"encoding/json"
"errors"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
"golang.org/x/crypto/bcrypt"
)
var (
ErrUserNotFound = errors.New("user not found")
ErrInvalidEmailOrPassword = errors.New("Invalid email or password")
)
func init() {
DB.AddTableWithName(User{}, "users").SetKeys(true, "Id")
}
// A User is a person that has administrative access to bactdb.
type User struct {
Id int64 `json:"id,omitempty"`
Email string `db:"email" json:"email"`
Password string `db:"password" json:"-"`
Name string `db:"name" json:"name"`
Role string `db:"role" json:"role"`
CreatedAt time.Time `db:"created_at" json:"createdAt"`
UpdatedAt time.Time `db:"updated_at" json:"updatedAt"`
DeletedAt NullTime `db:"deleted_at" json:"deletedAt"`
}
type UserJSON struct {
User *User `json:"user"`
}
type UsersJSON struct {
Users []*User `json:"users"`
}
func serveUsersList(w http.ResponseWriter, r *http.Request) {
var opt ListOptions
if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
users, err := dbGetUsers(&opt)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if users == nil {
users = []*User{}
}
data, err := json.Marshal(UsersJSON{Users: users})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Write(data)
}
func serveUser(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
user, err := dbGetUser(id)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
data, err := json.Marshal(UserJSON{User: user})
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Write(data)
}
func dbAuthenticate(email string, password string) error {
var user User
q := `SELECT * FROM users WHERE lower(email)=lower($1);`
if err := DBH.SelectOne(&user, q, email); err != nil {
return ErrInvalidEmailOrPassword
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
return ErrInvalidEmailOrPassword
}
return nil
}
func dbGetUsers(opt *ListOptions) ([]*User, error) {
var users []*User
sql := `SELECT * FROM users;`
if err := DBH.Select(&users, sql); err != nil {
return nil, err
}
return users, nil
}
func dbGetUser(id int64) (*User, error) {
var user User
q := `SELECT * FROM users WHERE id=$1;`
if err := DBH.SelectOne(&user, q, id); err != nil {
if err == sql.ErrNoRows {
return nil, ErrUserNotFound
}
return nil, err
}
return &user, nil
}
func dbGetUserByEmail(email string) (*User, error) {
var user User
q := `SELECT * FROM users WHERE lower(email)=lower($1);`
if err := DBH.SelectOne(&user, q, email); err != nil {
if err == sql.ErrNoRows {
return nil, ErrUserNotFound
}
return nil, err
}
return &user, nil
}