github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/service/api_key.go (about)

     1  package service
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	"gorm.io/gorm"
     8  
     9  	"github.com/pyroscope-io/pyroscope/pkg/model"
    10  )
    11  
    12  type APIKeyService struct {
    13  	db         *gorm.DB
    14  	bcryptCost int
    15  }
    16  
    17  func NewAPIKeyService(db *gorm.DB, bcryptCost int) APIKeyService {
    18  	return APIKeyService{
    19  		db:         db,
    20  		bcryptCost: bcryptCost,
    21  	}
    22  }
    23  
    24  func (svc APIKeyService) CreateAPIKey(ctx context.Context, params model.CreateAPIKeyParams) (model.APIKey, string, error) {
    25  	if err := params.Validate(); err != nil {
    26  		return model.APIKey{}, "", err
    27  	}
    28  	apiKey := model.APIKey{
    29  		Name:      params.Name,
    30  		Hash:      []byte{},
    31  		Role:      params.Role,
    32  		ExpiresAt: params.ExpiresAt,
    33  	}
    34  	var secret string
    35  	err := svc.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
    36  		_, err := findAPIKeyByName(tx, params.Name)
    37  		switch {
    38  		case errors.Is(err, model.ErrAPIKeyNotFound):
    39  		case err == nil:
    40  			return model.ErrAPIKeyNameExists
    41  		default:
    42  			return err
    43  		}
    44  		if err = tx.Create(&apiKey).Error; err != nil {
    45  			return err
    46  		}
    47  		var hash []byte
    48  		if secret, hash, err = model.GenerateAPIKeyWithCost(apiKey.ID, svc.bcryptCost); err != nil {
    49  			return err
    50  		}
    51  		apiKey.Hash = hash
    52  		return tx.Updates(&model.APIKey{ID: apiKey.ID, Hash: hash}).Error
    53  	})
    54  	if err != nil {
    55  		return model.APIKey{}, "", err
    56  	}
    57  	return apiKey, secret, nil
    58  }
    59  
    60  func (svc APIKeyService) FindAPIKeyByID(ctx context.Context, id uint) (model.APIKey, error) {
    61  	return findAPIKeyByID(svc.db.WithContext(ctx), id)
    62  }
    63  
    64  func (svc APIKeyService) FindAPIKeyByName(ctx context.Context, name string) (model.APIKey, error) {
    65  	return findAPIKeyByName(svc.db.WithContext(ctx), name)
    66  }
    67  
    68  func findAPIKeyByID(tx *gorm.DB, id uint) (model.APIKey, error) {
    69  	return findAPIKey(tx, model.APIKey{ID: id})
    70  }
    71  
    72  func findAPIKeyByName(tx *gorm.DB, apiKeyName string) (model.APIKey, error) {
    73  	return findAPIKey(tx, model.APIKey{Name: apiKeyName})
    74  }
    75  
    76  func findAPIKey(tx *gorm.DB, k model.APIKey) (model.APIKey, error) {
    77  	var apiKey model.APIKey
    78  	r := tx.Where(k).First(&apiKey)
    79  	switch {
    80  	case r.Error == nil:
    81  		return apiKey, nil
    82  	case errors.Is(r.Error, gorm.ErrRecordNotFound):
    83  		return model.APIKey{}, model.ErrAPIKeyNotFound
    84  	default:
    85  		return model.APIKey{}, r.Error
    86  	}
    87  }
    88  
    89  func (svc APIKeyService) GetAllAPIKeys(ctx context.Context) ([]model.APIKey, error) {
    90  	var apiKeys []model.APIKey
    91  	return apiKeys, svc.db.WithContext(ctx).Find(&apiKeys).Error
    92  }
    93  
    94  func (svc APIKeyService) DeleteAPIKeyByID(ctx context.Context, id uint) error {
    95  	return svc.db.WithContext(ctx).Delete(&model.APIKey{}, id).Error
    96  }