Implement delete and check token

This commit is contained in:
Nicolas Duhamel 2016-02-10 17:32:23 +01:00
parent a173f15a57
commit dc873a12a5
2 changed files with 78 additions and 7 deletions

View File

@ -1,6 +1,8 @@
package users package users
import ( import (
"fmt"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"gitlab.quimbo.fr/odwrtw/canape-sql/random" "gitlab.quimbo.fr/odwrtw/canape-sql/random"
) )
@ -11,7 +13,7 @@ CREATE TABLE users (
name text NOT NULL UNIQUE name text NOT NULL UNIQUE
); );
CREATE TABLE token ( CREATE TABLE tokens (
id SERIAL, id SERIAL,
value text NOT NULL UNIQUE, value text NOT NULL UNIQUE,
users_id integer REFERENCES users (id) ON DELETE CASCADE users_id integer REFERENCES users (id) ON DELETE CASCADE
@ -23,8 +25,10 @@ const (
updateUserQuery = `UPDATE users SET (name)=(:name);` updateUserQuery = `UPDATE users SET (name)=(:name);`
deleteUseQuery = `DELETE FROM users WHERE id=:id;` deleteUseQuery = `DELETE FROM users WHERE id=:id;`
addTokenQuery = `INSERT INTO token (value, users_id) VALUES ($1, $2) RETURNING id;` addTokenQuery = `INSERT INTO tokens (value, users_id) VALUES ($1, $2) RETURNING id;`
getTokensQuery = `SELECT id, value FROM token WHERE users_id=$1;` getTokensQuery = `SELECT id, value FROM tokens WHERE users_id=$1;`
checkTokenQuery = `SELECT count(*) FROM tokens WHERE users_id=$1 AND value=$2;`
deleteTokenQuery = `DELETE FROM tokens WHERE users_id=$1 AND value=$2;`
) )
// User represents an user // User represents an user
@ -33,6 +37,7 @@ type User struct {
Name string Name string
} }
// Token represents a token
type Token struct { type Token struct {
ID int ID int
Value string Value string
@ -77,6 +82,7 @@ func (u *User) Delete(ex *sqlx.DB) error {
return nil return nil
} }
// GetTokens returns all tokens owned by the user
func (u *User) GetTokens(ex *sqlx.DB) ([]*Token, error) { func (u *User) GetTokens(ex *sqlx.DB) ([]*Token, error) {
tokens := []*Token{} tokens := []*Token{}
err := ex.Select(&tokens, getTokensQuery, u.ID) err := ex.Select(&tokens, getTokensQuery, u.ID)
@ -86,6 +92,7 @@ func (u *User) GetTokens(ex *sqlx.DB) ([]*Token, error) {
return tokens, nil return tokens, nil
} }
// NewToken generates a new token for the user
func (u *User) NewToken(ex *sqlx.DB) (*Token, error) { func (u *User) NewToken(ex *sqlx.DB) (*Token, error) {
t := &Token{ t := &Token{
Value: random.String(50), Value: random.String(50),
@ -100,10 +107,28 @@ func (u *User) NewToken(ex *sqlx.DB) (*Token, error) {
return t, nil return t, nil
} }
func (u *User) CheckToken(ex *sqlx.DB, value string) error { // CheckToken checks if specified value exists in token's values for the user
return nil func (u *User) CheckToken(ex *sqlx.DB, value string) (bool, error) {
var count int
err := ex.QueryRowx(checkTokenQuery, u.ID, value).Scan(&count)
if err != nil {
return false, err
}
if count != 1 {
return false, nil
}
return true, nil
} }
// DeleteToken delete token by value
func (u *User) DeleteToken(ex *sqlx.DB, value string) error { func (u *User) DeleteToken(ex *sqlx.DB, value string) error {
r, err := ex.Exec(deleteTokenQuery, u.ID, value)
if err != nil {
return err
}
count, _ := r.RowsAffected()
if count != 1 {
return fmt.Errorf("Unexpected number of row deleted: %d", count)
}
return nil return nil
} }

View File

@ -12,7 +12,7 @@ import (
) )
const drop = ` const drop = `
DROP TABLE token; DROP TABLE tokens;
DROP TABLE users;` DROP TABLE users;`
var db *sqlx.DB var db *sqlx.DB
@ -109,6 +109,7 @@ func TestTokenAddDelete(t *testing.T) {
// Add many token // Add many token
_, err = u.NewToken(db) _, err = u.NewToken(db)
_, err = u.NewToken(db) _, err = u.NewToken(db)
token, err := u.NewToken(db)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -118,13 +119,32 @@ func TestTokenAddDelete(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if len(tokens) != 3 {
t.Fatalf("Unexpected number of token: %q", len(tokens))
}
// Delete token
err = u.DeleteToken(db, token.Value)
if err != nil {
t.Fatal(err)
}
tokens, _ = u.GetTokens(db)
if len(tokens) != 2 { if len(tokens) != 2 {
t.Fatalf("Unexpected number of token: %q", len(tokens)) t.Fatalf("Unexpected number of token: %q", len(tokens))
} }
// Delete a fake token
err = u.DeleteToken(db, "plop")
if err == nil {
t.Fatalf("We expect an error when try to delete a fake token")
}
if err.Error() != "Unexpected number of row deleted: 0" {
t.Fatalf("Unexpected error: %q", err)
}
// Remove user and test auto delete token // Remove user and test auto delete token
u.Delete(db) u.Delete(db)
q := `SELECT count(*) FROM token WHERE users_id=$1;` q := `SELECT count(*) FROM tokens WHERE users_id=$1;`
var count int var count int
err = db.QueryRowx(q, u.ID).Scan(&count) err = db.QueryRowx(q, u.ID).Scan(&count)
if err != nil { if err != nil {
@ -136,3 +156,29 @@ func TestTokenAddDelete(t *testing.T) {
}) })
} }
func TestTokenCheck(t *testing.T) {
sqltest.RunWithSchema(db, usersCreate, drop, t, func(db *sqlx.DB, t *testing.T) {
u := &User{Name: "plop"}
u.Add(db)
token, err := u.NewToken(db)
ok, err := u.CheckToken(db, token.Value)
if err != nil {
t.Fatal(err)
}
if !ok {
t.Fatalf("Token not found")
}
// test fake token
ok, err = u.CheckToken(db, "plop")
if err != nil {
t.Fatal(err)
}
if ok {
t.Fatalf("Token found otherwise we don't expect")
}
})
}