184 lines
4.4 KiB
Go
184 lines
4.4 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
"github.com/jmoiron/sqlx/types"
|
|
"github.com/odwrtw/polochon/lib/papi"
|
|
)
|
|
|
|
const (
|
|
addUserQuery = `INSERT INTO
|
|
users (name, hash, admin, polochon_id, token)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING id;`
|
|
getUserQuery = `SELECT * FROM users WHERE name=$1;`
|
|
getUserByIDQuery = `SELECT * FROM users WHERE id=$1;`
|
|
updateUserQuery = `UPDATE users SET
|
|
name=:name, hash=:hash, admin=:admin, activated=:activated,
|
|
rawconfig=:rawconfig, polochon_id=:polochon_id, token=:token,
|
|
polochon_activated=:polochon_activated
|
|
WHERE id=:id
|
|
RETURNING *;`
|
|
deleteUserQuery = `DELETE FROM users WHERE id=:id;`
|
|
|
|
getAllUsersQuery = `
|
|
SELECT u.*, tok.last_seen
|
|
FROM users u
|
|
LEFT OUTER JOIN (
|
|
SELECT username, MAX(last_used) AS last_seen
|
|
FROM tokens GROUP BY username
|
|
) AS tok
|
|
ON u.name = tok.username
|
|
ORDER by u.created_at;
|
|
`
|
|
getPolochonUsersQuery = `SELECT * FROM users WHERE polochon_id = $1;`
|
|
)
|
|
|
|
const (
|
|
// UserRole represents the user's role
|
|
UserRole = "user"
|
|
// AdminRole represents the admin's role
|
|
AdminRole = "admin"
|
|
)
|
|
|
|
// ErrUnknownUser returned when a user does'nt exist
|
|
var ErrUnknownUser = fmt.Errorf("users: user does'nt exist")
|
|
|
|
// User represents an user
|
|
type User struct {
|
|
BaseModel
|
|
Name string `json:"name"`
|
|
Hash string `json:"-"`
|
|
Admin bool `json:"admin"`
|
|
RawConfig types.JSONText `json:"raw_config"`
|
|
Token string `json:"token"`
|
|
Activated bool `json:"activated"`
|
|
PolochonID sql.NullString `json:"polochon_id" db:"polochon_id"`
|
|
PolochonActivated bool `json:"polochon_activated" db:"polochon_activated"`
|
|
Polochon *Polochon `json:"polochon"`
|
|
LastSeen *time.Time `json:"last_seen" db:"last_seen"`
|
|
}
|
|
|
|
// NewPapiClient creates a new papi client for the given user
|
|
func (u *User) NewPapiClient(db *sqlx.DB) (*papi.Client, error) {
|
|
polochon, err := u.GetPolochon(db)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client, err := papi.New(polochon.URL)
|
|
if err != nil {
|
|
return nil, errors.New("error getting papi client")
|
|
}
|
|
|
|
if u.Token != "" {
|
|
client.SetToken(u.Token)
|
|
}
|
|
return client, nil
|
|
}
|
|
|
|
// GetUser returns user with specified name
|
|
func GetUser(q sqlx.Queryer, name string) (*User, error) {
|
|
u := &User{}
|
|
err := q.QueryRowx(getUserQuery, name).StructScan(u)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, ErrUnknownUser
|
|
}
|
|
return nil, err
|
|
}
|
|
return u, nil
|
|
}
|
|
|
|
// GetUserByID returns user using its id
|
|
func GetUserByID(q sqlx.Queryer, id string) (*User, error) {
|
|
u := &User{}
|
|
err := q.QueryRowx(getUserByIDQuery, id).StructScan(u)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return nil, ErrUnknownUser
|
|
}
|
|
return nil, err
|
|
}
|
|
return u, nil
|
|
}
|
|
|
|
// GetAllUsers returns all the users
|
|
func GetAllUsers(db *sqlx.DB) ([]*User, error) {
|
|
users := []*User{}
|
|
err := db.Select(&users, getAllUsersQuery)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
// GetPolochonUsers returns all the users of a polochon
|
|
func GetPolochonUsers(db *sqlx.DB, id string) ([]*User, error) {
|
|
users := []*User{}
|
|
err := db.Select(&users, getPolochonUsersQuery, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return users, 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, u.Admin, u.PolochonID, u.Token).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() {
|
|
if err := rows.StructScan(u); 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(deleteUserQuery, u)
|
|
return err
|
|
}
|
|
|
|
// HasRole checks if a user as a role
|
|
func (u *User) HasRole(role string) bool {
|
|
if role == AdminRole && !u.Admin {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// IsAdmin checks if a user is admin
|
|
func (u *User) IsAdmin() bool {
|
|
return u.HasRole(AdminRole)
|
|
}
|
|
|
|
// IsActivated checks if a user is activated
|
|
func (u *User) IsActivated() bool {
|
|
return u.Activated
|
|
}
|
|
|
|
// GetPolochon returns the user's polochon
|
|
func (u *User) GetPolochon(db *sqlx.DB) (*Polochon, error) {
|
|
return GetPolochonByID(db, u.PolochonID.String)
|
|
}
|