Upgrade users routes to use interfaces
This commit is contained in:
parent
4143e02cfd
commit
3232d4ffbe
2 changed files with 44 additions and 65 deletions
|
@ -72,8 +72,8 @@ func Handler() http.Handler {
|
||||||
m.Handle("/authenticate", tokenHandler(j.GenerateToken())).Methods("POST")
|
m.Handle("/authenticate", tokenHandler(j.GenerateToken())).Methods("POST")
|
||||||
|
|
||||||
// Auth routes
|
// Auth routes
|
||||||
m.Handle("/users", j.Secure(http.HandlerFunc(serveUsersList), verifyClaims)).Methods("GET")
|
m.Handle("/users", j.Secure(http.HandlerFunc(handleLister(UserService{})), verifyClaims)).Methods("GET")
|
||||||
m.Handle("/users/{Id:.+}", j.Secure(http.HandlerFunc(serveUser), verifyClaims)).Methods("GET")
|
m.Handle("/users/{Id:.+}", j.Secure(http.HandlerFunc(handleGetter(UserService{})), verifyClaims)).Methods("GET")
|
||||||
|
|
||||||
// Path-based pattern matching subrouter
|
// Path-based pattern matching subrouter
|
||||||
s := m.PathPrefix("/{genus}").Subrouter()
|
s := m.PathPrefix("/{genus}").Subrouter()
|
||||||
|
|
105
users.go
105
users.go
|
@ -4,11 +4,9 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/url"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,7 +19,8 @@ func init() {
|
||||||
DB.AddTableWithName(User{}, "users").SetKeys(true, "Id")
|
DB.AddTableWithName(User{}, "users").SetKeys(true, "Id")
|
||||||
}
|
}
|
||||||
|
|
||||||
// A User is a person that has administrative access to bactdb.
|
type UserService struct{}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Id int64 `json:"id,omitempty"`
|
Id int64 `json:"id,omitempty"`
|
||||||
Email string `db:"email" json:"email"`
|
Email string `db:"email" json:"email"`
|
||||||
|
@ -33,60 +32,60 @@ type User struct {
|
||||||
DeletedAt NullTime `db:"deleted_at" json:"deletedAt"`
|
DeletedAt NullTime `db:"deleted_at" json:"deletedAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Users []*User
|
||||||
|
|
||||||
type UserJSON struct {
|
type UserJSON struct {
|
||||||
User *User `json:"user"`
|
User *User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UsersJSON struct {
|
type UsersJSON struct {
|
||||||
Users []*User `json:"users"`
|
Users *Users `json:"users"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func serveUsersList(w http.ResponseWriter, r *http.Request) {
|
func (u *User) marshal() ([]byte, error) {
|
||||||
|
return json.Marshal(&UserJSON{User: u})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Users) marshal() ([]byte, error) {
|
||||||
|
return json.Marshal(&UsersJSON{Users: u})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UserService) unmarshal(b []byte) (entity, error) {
|
||||||
|
var uj UserJSON
|
||||||
|
err := json.Unmarshal(b, &uj)
|
||||||
|
return uj.User, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u UserService) list(val *url.Values) (entity, error) {
|
||||||
|
if val == nil {
|
||||||
|
return nil, errors.New("must provide options")
|
||||||
|
}
|
||||||
var opt ListOptions
|
var opt ListOptions
|
||||||
if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil {
|
if err := schemaDecoder.Decode(&opt, *val); err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
return nil, err
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
users, err := dbGetUsers(&opt)
|
users := make(Users, 0)
|
||||||
if err != nil {
|
sql := `SELECT * FROM users;`
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
if err := DBH.Select(&users, sql); err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
if users == nil {
|
return &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) {
|
func (u UserService) get(id int64, genus string) (entity, error) {
|
||||||
id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
var user User
|
||||||
if err != nil {
|
q := `SELECT * FROM users WHERE id=$1;`
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
if err := DBH.SelectOne(&user, q, id); err != nil {
|
||||||
return
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, ErrUserNotFound
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return &user, nil
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for thermokarst/jwt: authentication callback
|
||||||
func dbAuthenticate(email string, password string) error {
|
func dbAuthenticate(email string, password string) error {
|
||||||
var user User
|
var user User
|
||||||
q := `SELECT * FROM users WHERE lower(email)=lower($1);`
|
q := `SELECT * FROM users WHERE lower(email)=lower($1);`
|
||||||
|
@ -99,27 +98,7 @@ func dbAuthenticate(email string, password string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func dbGetUsers(opt *ListOptions) ([]*User, error) {
|
// for thermokarst/jwt: setting user in claims bundle
|
||||||
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) {
|
func dbGetUserByEmail(email string) (*User, error) {
|
||||||
var user User
|
var user User
|
||||||
q := `SELECT * FROM users WHERE lower(email)=lower($1);`
|
q := `SELECT * FROM users WHERE lower(email)=lower($1);`
|
||||||
|
|
Reference in a new issue