diff --git a/handlers.go b/handlers.go index 1a609b0..2d96b3c 100644 --- a/handlers.go +++ b/handlers.go @@ -72,8 +72,8 @@ func Handler() http.Handler { m.Handle("/authenticate", tokenHandler(j.GenerateToken())).Methods("POST") // Auth routes - m.Handle("/users", j.Secure(http.HandlerFunc(serveUsersList), verifyClaims)).Methods("GET") - m.Handle("/users/{Id:.+}", j.Secure(http.HandlerFunc(serveUser), verifyClaims)).Methods("GET") + m.Handle("/users", j.Secure(http.HandlerFunc(handleLister(UserService{})), verifyClaims)).Methods("GET") + m.Handle("/users/{Id:.+}", j.Secure(http.HandlerFunc(handleGetter(UserService{})), verifyClaims)).Methods("GET") // Path-based pattern matching subrouter s := m.PathPrefix("/{genus}").Subrouter() diff --git a/users.go b/users.go index 9136bb0..d57b0b6 100644 --- a/users.go +++ b/users.go @@ -4,11 +4,9 @@ import ( "database/sql" "encoding/json" "errors" - "net/http" - "strconv" + "net/url" "time" - "github.com/gorilla/mux" "golang.org/x/crypto/bcrypt" ) @@ -21,7 +19,8 @@ func init() { DB.AddTableWithName(User{}, "users").SetKeys(true, "Id") } -// A User is a person that has administrative access to bactdb. +type UserService struct{} + type User struct { Id int64 `json:"id,omitempty"` Email string `db:"email" json:"email"` @@ -33,60 +32,60 @@ type User struct { DeletedAt NullTime `db:"deleted_at" json:"deletedAt"` } +type Users []*User + type UserJSON struct { User *User `json:"user"` } 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 - if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return + if err := schemaDecoder.Decode(&opt, *val); err != nil { + return nil, err } - users, err := dbGetUsers(&opt) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return + users := make(Users, 0) + sql := `SELECT * FROM users;` + if err := DBH.Select(&users, sql); err != nil { + return nil, err } - 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) + return &users, nil } -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 +func (u UserService) get(id int64, genus string) (entity, 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 } - - 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) + return &user, nil } +// for thermokarst/jwt: authentication callback func dbAuthenticate(email string, password string) error { var user User q := `SELECT * FROM users WHERE lower(email)=lower($1);` @@ -99,27 +98,7 @@ func dbAuthenticate(email string, password string) error { 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 -} - +// for thermokarst/jwt: setting user in claims bundle func dbGetUserByEmail(email string) (*User, error) { var user User q := `SELECT * FROM users WHERE lower(email)=lower($1);`