package tokens import ( "database/sql" "errors" "fmt" "time" "github.com/jmoiron/sqlx" "gitlab.quimbo.fr/odwrtw/canape/backend/sqly" ) 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;` 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 } // 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 }