153 lines
3.4 KiB
Go
153 lines
3.4 KiB
Go
package users
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
"gitlab.quimbo.fr/odwrtw/canape-sql/random"
|
|
"gitlab.quimbo.fr/odwrtw/canape-sql/sqly"
|
|
)
|
|
|
|
var Schema = sqly.Schema{
|
|
Tables: []sqly.SchemaTable{
|
|
sqly.SchemaTable{
|
|
Name: "users",
|
|
Sql: `
|
|
CREATE TABLE users (
|
|
id SERIAL PRIMARY KEY,
|
|
name text NOT NULL UNIQUE,
|
|
updated timestamp DEFAULT current_timestamp,
|
|
created timestamp DEFAULT current_timestamp
|
|
);`},
|
|
sqly.SchemaTable{
|
|
Name: "tokens",
|
|
Sql: `
|
|
CREATE TABLE tokens (
|
|
id SERIAL,
|
|
value text NOT NULL UNIQUE,
|
|
users_id integer REFERENCES users (id) ON DELETE CASCADE,
|
|
updated timestamp DEFAULT current_timestamp,
|
|
created timestamp DEFAULT current_timestamp
|
|
);
|
|
`},
|
|
},
|
|
Drop: `
|
|
DROP TABLE tokens;
|
|
DROP TABLE users;
|
|
`,
|
|
}
|
|
|
|
const (
|
|
addUserQuery = `INSERT INTO users (name) VALUES ($1) RETURNING id;`
|
|
getUserQuery = `SELECT * FROM users WHERE name=$1;`
|
|
updateUserQuery = `UPDATE users SET name=$1 RETURNING *;`
|
|
deleteUseQuery = `DELETE FROM users WHERE id=:id;`
|
|
|
|
addTokenQuery = `INSERT INTO tokens (value, users_id) VALUES ($1, $2) RETURNING id;`
|
|
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
|
|
type User struct {
|
|
sqly.BaseTable
|
|
Name string
|
|
}
|
|
|
|
// Token represents a token
|
|
type Token struct {
|
|
sqly.BaseTable
|
|
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 {
|
|
return nil, err
|
|
}
|
|
return u, nil
|
|
}
|
|
|
|
// Add user to database or raises an error
|
|
func (u *User) Add(q sqlx.Queryer) error {
|
|
var id int
|
|
err := q.QueryRowx(addUserQuery, u.Name).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 {
|
|
err := ex.Get(u, updateUserQuery, u.Name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
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 int
|
|
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
|
|
}
|