107 lines
2.7 KiB
Go
107 lines
2.7 KiB
Go
package tokens
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.quimbo.fr/odwrtw/canape/backend/sqly"
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
const (
|
|
addTokenQuery = `INSERT INTO tokens (token, username, ip, description) VALUES ($1, $2, $3, $4);`
|
|
getTokenQuery = `SELECT * FROM tokens WHERE token=$1;`
|
|
getUserTokenQuery = `SELECT * FROM tokens WHERE username=$1 and token=$2;`
|
|
getUserTokensQuery = `SELECT * FROM tokens WHERE username=$1;`
|
|
deleteTokenQuery = `DELETE FROM tokens WHERE username=$1 AND token=$2;`
|
|
deleteUserTokens = `DELETE FROM tokens WHERE username=$1;`
|
|
updateTokenQuery = `UPDATE tokens SET description=:description, user_agent=:user_agent, ip=:ip, last_used=now() WHERE token=:token RETURNING *;`
|
|
)
|
|
|
|
// Custom errors
|
|
var (
|
|
ErrTokenNotFound = errors.New("tokens: token not found")
|
|
)
|
|
|
|
// Token represents a token
|
|
type Token struct {
|
|
sqly.BaseModel
|
|
Username string `db:"username" json:"username"`
|
|
Token string `db:"token" json:"token"`
|
|
Description string `db:"description" json:"description"`
|
|
UserAgent string `db:"user_agent" json:"user_agent"`
|
|
IP string `db:"ip" json:"ip"`
|
|
LastUsed time.Time `db:"last_used" json:"last_used"`
|
|
}
|
|
|
|
// Add a token to the database
|
|
func (t *Token) Add(db *sqlx.DB) error {
|
|
_, err := db.Queryx(addTokenQuery, t.Token, t.Username, t.IP, t.Description)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetUserToken returns the token linked to a user
|
|
func GetUserToken(db *sqlx.DB, username, token string) (*Token, error) {
|
|
t := &Token{}
|
|
err := db.QueryRowx(getUserTokenQuery, username, token).StructScan(t)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, ErrTokenNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
return t, nil
|
|
}
|
|
|
|
// DeleteToken deletes a token
|
|
func DeleteToken(db *sqlx.DB, username, token string) error {
|
|
r, err := db.Exec(deleteTokenQuery, username, token)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
count, err := r.RowsAffected()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if count != 1 {
|
|
return fmt.Errorf("Unexpected number of row deleted: %d", count)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetUserTokens returns all tokens owned by the user
|
|
func GetUserTokens(db *sqlx.DB, username string) ([]*Token, error) {
|
|
tokens := []*Token{}
|
|
err := db.Select(&tokens, getUserTokensQuery, username)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return tokens, nil
|
|
}
|
|
|
|
// DeleteUserTokens deletes all the user's tokens
|
|
func DeleteUserTokens(db *sqlx.DB, username string) error {
|
|
_, err := db.Exec(deleteUserTokens, username)
|
|
return err
|
|
}
|
|
|
|
// Update updates a token
|
|
func (t *Token) Update(db *sqlx.DB) error {
|
|
rows, err := db.NamedQuery(updateTokenQuery, t)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for rows.Next() {
|
|
rows.StructScan(t)
|
|
}
|
|
return nil
|
|
}
|