184 lines
4.2 KiB
Go
184 lines
4.2 KiB
Go
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||
|
// See LICENSE for copying information.
|
||
|
|
||
|
package admin
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"io/ioutil"
|
||
|
"net/http"
|
||
|
|
||
|
"github.com/gorilla/mux"
|
||
|
|
||
|
"storj.io/common/macaroon"
|
||
|
"storj.io/common/uuid"
|
||
|
"storj.io/storj/satellite/console"
|
||
|
)
|
||
|
|
||
|
func (server *Server) addAPIKey(w http.ResponseWriter, r *http.Request) {
|
||
|
ctx := r.Context()
|
||
|
|
||
|
vars := mux.Vars(r)
|
||
|
projectUUIDString, ok := vars["project"]
|
||
|
if !ok {
|
||
|
httpJSONError(w, "project-uuid missing",
|
||
|
"", http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
projectUUID, err := uuid.FromString(projectUUIDString)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "invalid project-uuid",
|
||
|
err.Error(), http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
body, err := ioutil.ReadAll(r.Body)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "failed to read body",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
var input struct {
|
||
|
PartnerID uuid.UUID `json:"partnerId"`
|
||
|
Name string `json:"name"`
|
||
|
}
|
||
|
|
||
|
var output struct {
|
||
|
APIKey string `json:"apikey"`
|
||
|
}
|
||
|
|
||
|
err = json.Unmarshal(body, &input)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "failed to unmarshal request",
|
||
|
err.Error(), http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if input.Name == "" {
|
||
|
httpJSONError(w, "Name is not set",
|
||
|
"", http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
_, err = server.db.Console().APIKeys().GetByNameAndProjectID(ctx, input.Name, projectUUID)
|
||
|
if err == nil {
|
||
|
httpJSONError(w, "api-key with given name already exists",
|
||
|
"", http.StatusConflict)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
secret, err := macaroon.NewSecret()
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "could not create macaroon secret",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
key, err := macaroon.NewAPIKey(secret)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "could not create api-key",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
apikey := console.APIKeyInfo{
|
||
|
Name: input.Name,
|
||
|
ProjectID: projectUUID,
|
||
|
Secret: secret,
|
||
|
PartnerID: input.PartnerID,
|
||
|
}
|
||
|
|
||
|
_, err = server.db.Console().APIKeys().Create(ctx, key.Head(), apikey)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "unable to add api-key to database",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
output.APIKey = key.Serialize()
|
||
|
data, err := json.Marshal(output)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "json encoding failed",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
w.Header().Set("Content-Type", "application/json")
|
||
|
_, _ = w.Write(data) // nothing to do with the error response, probably the client requesting disappeared
|
||
|
}
|
||
|
|
||
|
func (server *Server) deleteAPIKey(w http.ResponseWriter, r *http.Request) {
|
||
|
ctx := r.Context()
|
||
|
|
||
|
vars := mux.Vars(r)
|
||
|
apikeyString, ok := vars["apikey"]
|
||
|
if !ok {
|
||
|
httpJSONError(w, "apikey missing",
|
||
|
"", http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
apikey, err := macaroon.ParseAPIKey(apikeyString)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "invalid apikey format",
|
||
|
err.Error(), http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
info, err := server.db.Console().APIKeys().GetByHead(ctx, apikey.Head())
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "could not get apikey id",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = server.db.Console().APIKeys().Delete(ctx, info.ID)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "unable to delete apikey",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (server *Server) deleteAPIKeyByName(w http.ResponseWriter, r *http.Request) {
|
||
|
ctx := r.Context()
|
||
|
|
||
|
vars := mux.Vars(r)
|
||
|
projectUUIDString, ok := vars["project"]
|
||
|
if !ok {
|
||
|
httpJSONError(w, "project-uuid missing",
|
||
|
"", http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
projectUUID, err := uuid.FromString(projectUUIDString)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "invalid project-uuid",
|
||
|
err.Error(), http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
apikeyName, ok := vars["name"]
|
||
|
if !ok {
|
||
|
httpJSONError(w, "apikey name missing",
|
||
|
"", http.StatusBadRequest)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
info, err := server.db.Console().APIKeys().GetByNameAndProjectID(ctx, apikeyName, projectUUID)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "could not get apikey id",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = server.db.Console().APIKeys().Delete(ctx, info.ID)
|
||
|
if err != nil {
|
||
|
httpJSONError(w, "unable to delete apikey",
|
||
|
err.Error(), http.StatusInternalServerError)
|
||
|
return
|
||
|
}
|
||
|
}
|