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 }