headscale/hscontrol/db/users.go

197 lines
4.1 KiB
Go
Raw Normal View History

package db
import (
2021-06-24 09:44:19 -04:00
"errors"
"github.com/juanfont/headscale/hscontrol/types"
"github.com/juanfont/headscale/hscontrol/util"
2021-08-05 13:23:02 -04:00
"github.com/rs/zerolog/log"
2021-06-24 09:44:19 -04:00
"gorm.io/gorm"
)
var (
ErrUserExists = errors.New("user already exists")
ErrUserNotFound = errors.New("user not found")
ErrUserStillHasNodes = errors.New("user not empty: node(s) found")
)
// CreateUser creates a new User. Returns error if could not be created
// or another user already exists.
func (hsdb *HSDatabase) CreateUser(name string) (*types.User, error) {
hsdb.mu.Lock()
defer hsdb.mu.Unlock()
err := util.CheckForFQDNRules(name)
if err != nil {
return nil, err
}
user := types.User{}
if err := hsdb.db.Where("name = ?", name).First(&user).Error; err == nil {
return nil, ErrUserExists
}
user.Name = name
if err := hsdb.db.Create(&user).Error; err != nil {
2021-08-05 13:23:02 -04:00
log.Error().
Str("func", "CreateUser").
2021-08-05 13:23:02 -04:00
Err(err).
Msg("Could not create row")
2021-11-14 10:46:09 -05:00
return nil, err
}
2021-11-14 10:46:09 -05:00
return &user, nil
}
// DestroyUser destroys a User. Returns error if the User does
2023-09-24 07:42:05 -04:00
// not exist or if there are nodes associated with it.
func (hsdb *HSDatabase) DestroyUser(name string) error {
hsdb.mu.Lock()
defer hsdb.mu.Unlock()
user, err := hsdb.getUser(name)
if err != nil {
return ErrUserNotFound
}
2023-09-24 07:42:05 -04:00
nodes, err := hsdb.listNodesByUser(name)
if err != nil {
return err
}
2023-09-24 07:42:05 -04:00
if len(nodes) > 0 {
return ErrUserStillHasNodes
}
keys, err := hsdb.listPreAuthKeys(name)
if err != nil {
return err
}
for _, key := range keys {
err = hsdb.destroyPreAuthKey(key)
2021-11-13 15:24:32 -05:00
if err != nil {
return err
}
}
if result := hsdb.db.Unscoped().Delete(&user); result.Error != nil {
return result.Error
}
return nil
}
// RenameUser renames a User. Returns error if the User does
// not exist or if another User exists with the new name.
func (hsdb *HSDatabase) RenameUser(oldName, newName string) error {
hsdb.mu.Lock()
defer hsdb.mu.Unlock()
var err error
oldUser, err := hsdb.getUser(oldName)
2021-10-16 11:20:06 -04:00
if err != nil {
return err
}
err = util.CheckForFQDNRules(newName)
if err != nil {
return err
}
_, err = hsdb.getUser(newName)
2021-10-16 11:20:06 -04:00
if err == nil {
return ErrUserExists
2021-10-16 11:20:06 -04:00
}
if !errors.Is(err, ErrUserNotFound) {
2021-10-16 11:20:06 -04:00
return err
}
oldUser.Name = newName
2021-10-16 11:20:06 -04:00
if result := hsdb.db.Save(&oldUser); result.Error != nil {
2021-10-16 11:20:06 -04:00
return result.Error
}
return nil
}
// GetUser fetches a user by name.
func (hsdb *HSDatabase) GetUser(name string) (*types.User, error) {
hsdb.mu.RLock()
defer hsdb.mu.RUnlock()
return hsdb.getUser(name)
}
func (hsdb *HSDatabase) getUser(name string) (*types.User, error) {
user := types.User{}
if result := hsdb.db.First(&user, "name = ?", name); errors.Is(
2021-11-13 03:36:45 -05:00
result.Error,
gorm.ErrRecordNotFound,
) {
return nil, ErrUserNotFound
}
2021-11-14 10:46:09 -05:00
return &user, nil
}
// ListUsers gets all the existing users.
func (hsdb *HSDatabase) ListUsers() ([]types.User, error) {
hsdb.mu.RLock()
defer hsdb.mu.RUnlock()
return hsdb.listUsers()
}
func (hsdb *HSDatabase) listUsers() ([]types.User, error) {
users := []types.User{}
if err := hsdb.db.Find(&users).Error; err != nil {
return nil, err
}
2021-11-14 10:46:09 -05:00
return users, nil
}
2023-09-24 07:42:05 -04:00
// ListNodesByUser gets all the nodes in a given user.
func (hsdb *HSDatabase) ListNodesByUser(name string) (types.Nodes, error) {
hsdb.mu.RLock()
defer hsdb.mu.RUnlock()
2023-09-24 07:42:05 -04:00
return hsdb.listNodesByUser(name)
}
2023-09-24 07:42:05 -04:00
func (hsdb *HSDatabase) listNodesByUser(name string) (types.Nodes, error) {
err := util.CheckForFQDNRules(name)
if err != nil {
return nil, err
}
user, err := hsdb.getUser(name)
if err != nil {
return nil, err
}
2023-09-24 07:42:05 -04:00
nodes := types.Nodes{}
if err := hsdb.db.Preload("AuthKey").Preload("AuthKey.User").Preload("User").Where(&types.Node{UserID: user.ID}).Find(&nodes).Error; err != nil {
return nil, err
}
2021-11-14 10:46:09 -05:00
2023-09-24 07:42:05 -04:00
return nodes, nil
}
2023-09-24 07:42:05 -04:00
// AssignNodeToUser assigns a Node to a user.
func (hsdb *HSDatabase) AssignNodeToUser(node *types.Node, username string) error {
hsdb.mu.Lock()
defer hsdb.mu.Unlock()
err := util.CheckForFQDNRules(username)
if err != nil {
return err
}
user, err := hsdb.getUser(username)
if err != nil {
return err
}
2023-09-24 07:42:05 -04:00
node.User = *user
if result := hsdb.db.Save(&node); result.Error != nil {
2022-05-02 05:47:21 -04:00
return result.Error
}
2021-11-14 10:46:09 -05:00
return nil
}