diff --git a/pkg/api/auth.go b/pkg/api/auth.go index 882ccb8..7582d44 100644 --- a/pkg/api/auth.go +++ b/pkg/api/auth.go @@ -31,10 +31,14 @@ var LoginHandler = HandlerFunc(func(w http.ResponseWriter, r *http.Request) erro var l login json.NewDecoder(r.Body).Decode(&l) + // find user with given email u, err := datastore.GetUserByEmail(l.Email) + if err != nil && err != datastore.ErrNoResults { + return err + } // compare pwd - if err != nil || bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(l.Password)) != nil { + if err == datastore.ErrNoResults || bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(l.Password)) != nil { w.WriteHeader(http.StatusUnauthorized) return respond(w, envelope{Error: "invalid_credentials"}) } @@ -69,7 +73,7 @@ func Authorize(next http.Handler) http.Handler { session, _ := store.Get(r, "auth") userID, ok := session.Values["user_id"] - if !ok { + if session.IsNew || !ok { w.WriteHeader(http.StatusUnauthorized) return } diff --git a/pkg/api/http.go b/pkg/api/http.go index 7a387ec..8b83133 100644 --- a/pkg/api/http.go +++ b/pkg/api/http.go @@ -32,8 +32,8 @@ func HandleError(w http.ResponseWriter, r *http.Request, err error) { } type envelope struct { - Data interface{} - Error interface{} `json:"omitempty"` + Data interface{} `json:",omitempty"` + Error interface{} `json:",omitempty"` } func respond(w http.ResponseWriter, d interface{}) error { diff --git a/pkg/datastore/store.go b/pkg/datastore/datastore.go similarity index 92% rename from pkg/datastore/store.go rename to pkg/datastore/datastore.go index 5b58cbe..bcd43ca 100644 --- a/pkg/datastore/store.go +++ b/pkg/datastore/datastore.go @@ -2,6 +2,7 @@ package datastore import ( "database/sql" + "errors" "fmt" _ "github.com/go-sql-driver/mysql" // mysql driver "github.com/jmoiron/sqlx" @@ -15,6 +16,9 @@ var DB *sql.DB var dbx *sqlx.DB +// ErrNoResults is returned when a query yielded 0 results +var ErrNoResults = errors.New("query returned 0 results") + // Init creates a database connection pool (using sqlx) func Init(driver string, host string, name string, user string, password string) *sqlx.DB { dbx = New(driver, getDSN(driver, host, name, user, password)) diff --git a/pkg/datastore/users.go b/pkg/datastore/users.go index ddbc101..2631910 100644 --- a/pkg/datastore/users.go +++ b/pkg/datastore/users.go @@ -1,31 +1,39 @@ package datastore import ( + "database/sql" "github.com/usefathom/fathom/pkg/models" ) -var u models.User - // GetUser retrieves user from datastore by its ID -func GetUser(id int64) (*models.User, error) { - stmt, err := DB.Prepare("SELECT id, email FROM users WHERE id = ? LIMIT 1") +func GetUser(ID int64) (*models.User, error) { + u := &models.User{} + err := dbx.Get(u, dbx.Rebind("SELECT * FROM users WHERE id = ? LIMIT 1"), ID) + if err != nil { + if err == sql.ErrNoRows { + return nil, ErrNoResults + } + return nil, err } - err = stmt.QueryRow(id).Scan(&u.ID, &u.Email) - return &u, err + return u, err } // GetUserByEmail retrieves user from datastore by its email func GetUserByEmail(email string) (*models.User, error) { - stmt, err := DB.Prepare("SELECT id, email, password FROM users WHERE email = ? LIMIT 1") + u := &models.User{} + err := dbx.Get(u, dbx.Rebind("SELECT * FROM users WHERE email = ? LIMIT 1"), email) if err != nil { + if err == sql.ErrNoRows { + return nil, ErrNoResults + } + return nil, err } - err = stmt.QueryRow(email).Scan(&u.ID, &u.Email, &u.Password) - return &u, err + return u, err } // SaveUser inserts the user model in the connected database