Files
ionscale/internal/domain/auth_key.go
T
Johan Siebens 5ad89ff02f initial working version
Signed-off-by: Johan Siebens <johan.siebens@gmail.com>
2022-05-09 21:54:06 +02:00

110 lines
2.3 KiB
Go

package domain
import (
"context"
"errors"
"fmt"
"github.com/jsiebens/ionscale/internal/util"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
"strings"
"time"
)
func CreateAuthKey(tailnet *Tailnet, user *User, ephemeral bool, tags Tags, expiresAt *time.Time) (string, *AuthKey) {
key := util.RandStringBytes(12)
pwd := util.RandStringBytes(22)
value := fmt.Sprintf("%s_%s", key, pwd)
hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost)
if err != nil {
panic(err)
}
return value, &AuthKey{
ID: util.NextID(),
Key: key,
Hash: string(hash),
Ephemeral: ephemeral,
Tags: tags,
CreatedAt: time.Now().UTC(),
ExpiresAt: expiresAt,
TailnetID: tailnet.ID,
UserID: user.ID,
}
}
type AuthKey struct {
ID uint64 `gorm:"primary_key;autoIncrement:false"`
Key string `gorm:"type:varchar(64);unique_index"`
Hash string
Ephemeral bool
Tags Tags
CreatedAt time.Time
ExpiresAt *time.Time
TailnetID uint64
Tailnet Tailnet
UserID uint64
User User
}
func (r *repository) SaveAuthKey(ctx context.Context, key *AuthKey) error {
tx := r.withContext(ctx).Save(key)
if tx.Error != nil {
return tx.Error
}
return nil
}
func (r *repository) DeleteAuthKey(ctx context.Context, id uint64) (bool, error) {
tx := r.withContext(ctx).Delete(&AuthKey{}, id)
return tx.RowsAffected == 1, tx.Error
}
func (r *repository) ListAuthKeys(ctx context.Context, tailnetID uint64) ([]AuthKey, error) {
var authKeys = []AuthKey{}
tx := (r.withContext(ctx).
Preload("User").
Preload("Tailnet")).
Where("tailnet_id = ?", tailnetID).
Find(&authKeys)
if tx.Error != nil {
return nil, tx.Error
}
return authKeys, nil
}
func (r *repository) LoadAuthKey(ctx context.Context, key string) (*AuthKey, error) {
split := strings.Split(key, "_")
if len(split) != 2 {
return nil, nil
}
var m AuthKey
tx := r.withContext(ctx).Preload("User").Preload("Tailnet").First(&m, "key = ?", split[0])
if errors.Is(tx.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
if tx.Error != nil {
return nil, tx.Error
}
if err := bcrypt.CompareHashAndPassword([]byte(m.Hash), []byte(split[1])); err != nil {
return nil, nil
}
if !m.ExpiresAt.IsZero() && m.ExpiresAt.Before(time.Now()) {
return nil, nil
}
return &m, nil
}