package users import ( "fmt" "github.com/jmoiron/sqlx" "gitlab.quimbo.fr/odwrtw/canape-sql/random" "gitlab.quimbo.fr/odwrtw/canape-sql/sqly" ) const ( addUserQuery = `INSERT INTO users (name, hash) VALUES ($1, $2) RETURNING id;` getUserQuery = `SELECT * FROM users WHERE name=$1;` updateUserQuery = `UPDATE users SET name=:name, hash=:hash RETURNING *;` deleteUseQuery = `DELETE FROM users WHERE id=:id;` addTokenQuery = `INSERT INTO tokens (value, user_id) VALUES ($1, $2) RETURNING id;` getTokensQuery = `SELECT id, value FROM tokens WHERE user_id=$1;` checkTokenQuery = `SELECT count(*) FROM tokens WHERE user_id=$1 AND value=$2;` deleteTokenQuery = `DELETE FROM tokens WHERE user_id=$1 AND value=$2;` ) // ErrUnknownUser returned web a user does'nt exist var ErrUnknownUser = fmt.Errorf("users: user does'nt exist") // User represents an user type User struct { sqly.BaseModel Name string Hash string } // Token represents a token type Token struct { sqly.BaseModel Value string } // Get returns user with specified name func Get(q sqlx.Queryer, name string) (*User, error) { u := &User{} err := q.QueryRowx(getUserQuery, name).StructScan(u) if err != nil { if err.Error() == "sql: no rows in result set" { return nil, ErrUnknownUser } return nil, err } return u, nil } // Add user to database or raises an error func (u *User) Add(q sqlx.Queryer) error { var id string err := q.QueryRowx(addUserQuery, u.Name, u.Hash).Scan(&id) if err != nil { return err } u.ID = id return nil } // Update user on database or raise an error func (u *User) Update(ex *sqlx.DB) error { rows, err := ex.NamedQuery(updateUserQuery, u) if err != nil { return err } for rows.Next() { rows.StructScan(u) } return nil } // Delete user from database or raise an error func (u *User) Delete(ex *sqlx.DB) error { _, err := ex.NamedExec(deleteUseQuery, u) if err != nil { return err } return nil } // GetTokens returns all tokens owned by the user 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 } // NewToken generates a new token for the user func (u *User) NewToken(ex *sqlx.DB) (*Token, error) { t := &Token{ Value: random.String(50), } var id string err := ex.QueryRowx(addTokenQuery, t.Value, u.ID).Scan(&id) if err != nil { return nil, err } t.ID = id return t, nil } // CheckToken checks if specified value exists in token's values for the user 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 { 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 } // GetHash implements auth.User interface func (u *User) GetHash() string { return u.Hash }