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

     1  package api
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"net/http"
     7  	"time"
     8  
     9  	"github.com/pyroscope-io/pyroscope/pkg/model"
    10  	"github.com/pyroscope-io/pyroscope/pkg/server/httputils"
    11  	"github.com/sirupsen/logrus"
    12  )
    13  
    14  //go:generate mockgen -destination mocks/api_key.go -package mocks . APIKeyService
    15  
    16  type APIKeyService interface {
    17  	CreateAPIKey(context.Context, model.CreateAPIKeyParams) (model.APIKey, string, error)
    18  	GetAllAPIKeys(context.Context) ([]model.APIKey, error)
    19  	DeleteAPIKeyByID(context.Context, uint) error
    20  }
    21  
    22  type APIKeyHandler struct {
    23  	logger        logrus.FieldLogger
    24  	apiKeyService APIKeyService
    25  	httpUtils     httputils.Utils
    26  }
    27  
    28  func NewAPIKeyHandler(logger logrus.FieldLogger, apiKeyService APIKeyService, httpUtils httputils.Utils) APIKeyHandler {
    29  	return APIKeyHandler{
    30  		logger:        logger,
    31  		apiKeyService: apiKeyService,
    32  		httpUtils:     httpUtils,
    33  	}
    34  }
    35  
    36  // apiKey represents a key fetched with a service query.
    37  type apiKey struct {
    38  	ID         uint       `json:"id"`
    39  	Name       string     `json:"name"`
    40  	Role       model.Role `json:"role"`
    41  	LastSeenAt *time.Time `json:"lastSeenAt,omitempty"`
    42  	ExpiresAt  *time.Time `json:"expiresAt,omitempty"`
    43  	CreatedAt  time.Time  `json:"createdAt"`
    44  }
    45  
    46  // generatedAPIKey represents newly generated API key with the JWT token.
    47  type generatedAPIKey struct {
    48  	ID        uint       `json:"id"`
    49  	Name      string     `json:"name"`
    50  	Role      model.Role `json:"role"`
    51  	Key       string     `json:"key"`
    52  	ExpiresAt *time.Time `json:"expiresAt,omitempty"`
    53  	CreatedAt time.Time  `json:"createdAt"`
    54  }
    55  
    56  type createAPIKeyRequest struct {
    57  	Name       string     `json:"name"`
    58  	Role       model.Role `json:"role"`
    59  	TTLSeconds int64      `json:"ttlSeconds,omitempty"`
    60  }
    61  
    62  func apiKeyFromModel(m model.APIKey) apiKey {
    63  	return apiKey{
    64  		ID:         m.ID,
    65  		Name:       m.Name,
    66  		Role:       m.Role,
    67  		ExpiresAt:  m.ExpiresAt,
    68  		LastSeenAt: m.LastSeenAt,
    69  		CreatedAt:  m.CreatedAt,
    70  	}
    71  }
    72  
    73  func generatedAPIKeyFromModel(m model.APIKey) generatedAPIKey {
    74  	return generatedAPIKey{
    75  		ID:        m.ID,
    76  		Name:      m.Name,
    77  		Role:      m.Role,
    78  		ExpiresAt: m.ExpiresAt,
    79  		CreatedAt: m.CreatedAt,
    80  	}
    81  }
    82  
    83  func (h APIKeyHandler) CreateAPIKey(w http.ResponseWriter, r *http.Request) {
    84  	var req createAPIKeyRequest
    85  	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
    86  		h.httpUtils.HandleError(r, w, httputils.JSONError{Err: err})
    87  		return
    88  	}
    89  	params := model.CreateAPIKeyParams{
    90  		Name: req.Name,
    91  		Role: req.Role,
    92  	}
    93  	if req.TTLSeconds > 0 {
    94  		expiresAt := time.Now().Add(time.Duration(req.TTLSeconds) * time.Second)
    95  		params.ExpiresAt = &expiresAt
    96  	}
    97  	ak, secret, err := h.apiKeyService.CreateAPIKey(r.Context(), params)
    98  	if err != nil {
    99  		h.httpUtils.HandleError(r, w, err)
   100  		return
   101  	}
   102  	k := generatedAPIKeyFromModel(ak)
   103  	k.Key = secret
   104  	w.WriteHeader(http.StatusCreated)
   105  	h.httpUtils.MustJSON(r, w, k)
   106  }
   107  
   108  func (h APIKeyHandler) ListAPIKeys(w http.ResponseWriter, r *http.Request) {
   109  	u, err := h.apiKeyService.GetAllAPIKeys(r.Context())
   110  	if err != nil {
   111  		h.httpUtils.HandleError(r, w, err)
   112  		return
   113  	}
   114  	apiKeys := make([]apiKey, len(u))
   115  	for i := range u {
   116  		apiKeys[i] = apiKeyFromModel(u[i])
   117  	}
   118  	h.httpUtils.MustJSON(r, w, apiKeys)
   119  }
   120  
   121  func (h APIKeyHandler) DeleteAPIKey(w http.ResponseWriter, r *http.Request) {
   122  	id, err := h.httpUtils.IDFromRequest(r)
   123  	if err != nil {
   124  		h.httpUtils.HandleError(r, w, err)
   125  		return
   126  	}
   127  	if err = h.apiKeyService.DeleteAPIKeyByID(r.Context(), id); err != nil {
   128  		h.httpUtils.HandleError(r, w, err)
   129  		return
   130  	}
   131  	w.WriteHeader(http.StatusNoContent)
   132  }