From a173f15a577fe296b7cc6fa766ce16b747d85839 Mon Sep 17 00:00:00 2001 From: Nicolas Duhamel Date: Wed, 10 Feb 2016 16:15:05 +0100 Subject: [PATCH] Implement token add and get --- random/random.go | 37 ++++++++++++++++++++++++++++++++++ users.go | 52 ++++++++++++++++++++++++++++++++++++++++++++++-- users_test.go | 44 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 random/random.go diff --git a/random/random.go b/random/random.go new file mode 100644 index 0000000..86ea8e5 --- /dev/null +++ b/random/random.go @@ -0,0 +1,37 @@ +package random + +import ( + "math/rand" + "time" +) + +func init() { + rand.Seed(time.Now().UnixNano()) +} + +const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const ( + letterIdxBits = 6 // 6 bits to represent a letter index + letterIdxMask = 1<= 0; { + if remain == 0 { + cache, remain = src.Int63(), letterIdxMax + } + if idx := int(cache & letterIdxMask); idx < len(letterBytes) { + b[i] = letterBytes[idx] + i-- + } + cache >>= letterIdxBits + remain-- + } + + return string(b) +} diff --git a/users.go b/users.go index 4298a2a..a20fc2a 100644 --- a/users.go +++ b/users.go @@ -1,18 +1,30 @@ package users -import "github.com/jmoiron/sqlx" +import ( + "github.com/jmoiron/sqlx" + "gitlab.quimbo.fr/odwrtw/canape-sql/random" +) const usersCreate = ` CREATE TABLE users ( - id SERIAL, + id SERIAL PRIMARY KEY, name text NOT NULL UNIQUE ); + +CREATE TABLE token ( + id SERIAL, + value text NOT NULL UNIQUE, + users_id integer REFERENCES users (id) ON DELETE CASCADE +); ` const ( addUserQuery = `INSERT INTO users (name) VALUES ($1) RETURNING id;` getUserQuery = `SELECT * FROM users WHERE name=$1;` updateUserQuery = `UPDATE users SET (name)=(:name);` deleteUseQuery = `DELETE FROM users WHERE id=:id;` + + addTokenQuery = `INSERT INTO token (value, users_id) VALUES ($1, $2) RETURNING id;` + getTokensQuery = `SELECT id, value FROM token WHERE users_id=$1;` ) // User represents an user @@ -21,6 +33,11 @@ type User struct { Name string } +type Token struct { + ID int + Value string +} + // Get returns user with specified name func Get(q sqlx.Queryer, name string) (*User, error) { u := &User{} @@ -59,3 +76,34 @@ func (u *User) Delete(ex *sqlx.DB) error { } return nil } + +func (u *User) GetTokens(ex *sqlx.DB) ([]*Token, error) { + tokens := []*Token{} + err := ex.Select(&tokens, getTokensQuery, u.ID) + if err != nil { + return nil, err + } + return tokens, nil +} + +func (u *User) NewToken(ex *sqlx.DB) (*Token, error) { + t := &Token{ + Value: random.String(50), + } + + var id int + err := ex.QueryRowx(addTokenQuery, t.Value, u.ID).Scan(&id) + if err != nil { + return nil, err + } + t.ID = id + return t, nil +} + +func (u *User) CheckToken(ex *sqlx.DB, value string) error { + return nil +} + +func (u *User) DeleteToken(ex *sqlx.DB, value string) error { + return nil +} diff --git a/users_test.go b/users_test.go index 0d9f841..f38043e 100644 --- a/users_test.go +++ b/users_test.go @@ -11,7 +11,9 @@ import ( "github.com/lib/pq" ) -const drop = `DROP TABLE users;` +const drop = ` +DROP TABLE token; +DROP TABLE users;` var db *sqlx.DB @@ -94,3 +96,43 @@ func TestUser(t *testing.T) { } }) } + +func TestTokenAddDelete(t *testing.T) { + sqltest.RunWithSchema(db, usersCreate, drop, t, func(db *sqlx.DB, t *testing.T) { + // Add a new user + u := &User{Name: "plop"} + err := u.Add(db) + if err != nil { + t.Fatal(err) + } + + // Add many token + _, err = u.NewToken(db) + _, err = u.NewToken(db) + if err != nil { + t.Fatal(err) + } + + // Get token + tokens, err := u.GetTokens(db) + if err != nil { + t.Fatal(err) + } + if len(tokens) != 2 { + t.Fatalf("Unexpected number of token: %q", len(tokens)) + } + + // Remove user and test auto delete token + u.Delete(db) + q := `SELECT count(*) FROM token WHERE users_id=$1;` + var count int + err = db.QueryRowx(q, u.ID).Scan(&count) + if err != nil { + t.Fatal(err) + } + if count != 0 { + t.Fatalf("Unexpected number of token: %d", count) + } + + }) +}