2021-11-12 20:48:29 +00:00
|
|
|
// Copyright (C) 2021 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package admin
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"github.com/gorilla/mux"
|
|
|
|
|
|
|
|
"storj.io/common/storj"
|
|
|
|
"storj.io/common/uuid"
|
|
|
|
"storj.io/storj/satellite/buckets"
|
|
|
|
)
|
|
|
|
|
2021-11-30 17:47:14 +00:00
|
|
|
func validateBucketPathParameters(vars map[string]string) (project uuid.NullUUID, bucket []byte, err error) {
|
2021-11-12 20:48:29 +00:00
|
|
|
projectUUIDString, ok := vars["project"]
|
|
|
|
if !ok {
|
|
|
|
return project, bucket, fmt.Errorf("project-uuid missing")
|
|
|
|
}
|
|
|
|
|
2023-09-05 20:28:39 +01:00
|
|
|
project.UUID, err = uuidFromString(projectUUIDString)
|
2021-11-12 20:48:29 +00:00
|
|
|
if err != nil {
|
|
|
|
return project, bucket, fmt.Errorf("project-uuid is not a valid uuid")
|
|
|
|
}
|
|
|
|
project.Valid = true
|
|
|
|
|
|
|
|
bucketName := vars["bucket"]
|
|
|
|
if len(bucketName) == 0 {
|
|
|
|
return project, bucket, fmt.Errorf("bucket name is missing")
|
|
|
|
}
|
|
|
|
|
|
|
|
bucket = []byte(bucketName)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func parsePlacementConstraint(regionCode string) (storj.PlacementConstraint, error) {
|
|
|
|
switch regionCode {
|
|
|
|
case "EU":
|
|
|
|
return storj.EU, nil
|
|
|
|
case "EEA":
|
|
|
|
return storj.EEA, nil
|
|
|
|
case "US":
|
|
|
|
return storj.US, nil
|
|
|
|
case "DE":
|
|
|
|
return storj.DE, nil
|
2023-05-24 15:59:47 +01:00
|
|
|
case "NR":
|
|
|
|
return storj.NR, nil
|
2021-11-12 20:48:29 +00:00
|
|
|
case "":
|
2023-10-05 03:43:08 +01:00
|
|
|
return storj.DefaultPlacement, fmt.Errorf("missing region parameter")
|
2021-11-12 20:48:29 +00:00
|
|
|
default:
|
2023-10-05 03:43:08 +01:00
|
|
|
return storj.DefaultPlacement, fmt.Errorf("unrecognized region parameter: %s", regionCode)
|
2021-11-12 20:48:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (server *Server) updateBucket(w http.ResponseWriter, r *http.Request, placement storj.PlacementConstraint) {
|
|
|
|
ctx := r.Context()
|
|
|
|
|
2021-11-30 17:47:14 +00:00
|
|
|
project, bucket, err := validateBucketPathParameters(mux.Vars(r))
|
2021-11-12 20:48:29 +00:00
|
|
|
if err != nil {
|
|
|
|
sendJSONError(w, err.Error(), "", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := server.buckets.GetBucket(ctx, bucket, project.UUID)
|
|
|
|
if err != nil {
|
2023-04-13 13:04:07 +01:00
|
|
|
if buckets.ErrBucketNotFound.Has(err) {
|
2021-11-12 20:48:29 +00:00
|
|
|
sendJSONError(w, "bucket does not exist", "", http.StatusBadRequest)
|
|
|
|
} else {
|
|
|
|
sendJSONError(w, "unable to create geofence for bucket", err.Error(), http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
b.Placement = placement
|
|
|
|
|
2021-12-01 15:33:41 +00:00
|
|
|
_, err = server.buckets.UpdateBucket(ctx, b)
|
2021-11-12 20:48:29 +00:00
|
|
|
if err != nil {
|
|
|
|
switch {
|
2023-04-13 13:04:07 +01:00
|
|
|
case buckets.ErrBucketNotFound.Has(err):
|
2021-11-12 20:48:29 +00:00
|
|
|
sendJSONError(w, "bucket does not exist", "", http.StatusBadRequest)
|
|
|
|
case buckets.ErrBucketNotEmpty.Has(err):
|
|
|
|
sendJSONError(w, "bucket must be empty", "", http.StatusBadRequest)
|
|
|
|
default:
|
|
|
|
sendJSONError(w, "unable to create geofence for bucket", err.Error(), http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-12-01 15:33:41 +00:00
|
|
|
w.WriteHeader(http.StatusOK)
|
2021-11-12 20:48:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (server *Server) createGeofenceForBucket(w http.ResponseWriter, r *http.Request) {
|
|
|
|
placement, err := parsePlacementConstraint(r.URL.Query().Get("region"))
|
|
|
|
if err != nil {
|
2023-05-24 15:59:47 +01:00
|
|
|
sendJSONError(w, err.Error(), "available: EU, EEA, US, DE, NR", http.StatusBadRequest)
|
2021-11-12 20:48:29 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
server.updateBucket(w, r, placement)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (server *Server) deleteGeofenceForBucket(w http.ResponseWriter, r *http.Request) {
|
2023-10-05 03:43:08 +01:00
|
|
|
server.updateBucket(w, r, storj.DefaultPlacement)
|
2021-11-12 20:48:29 +00:00
|
|
|
}
|
|
|
|
|
2021-11-30 17:47:14 +00:00
|
|
|
func (server *Server) getBucketInfo(w http.ResponseWriter, r *http.Request) {
|
2021-11-12 20:48:29 +00:00
|
|
|
ctx := r.Context()
|
|
|
|
|
2021-11-30 17:47:14 +00:00
|
|
|
project, bucket, err := validateBucketPathParameters(mux.Vars(r))
|
2021-11-12 20:48:29 +00:00
|
|
|
if err != nil {
|
|
|
|
sendJSONError(w, err.Error(), "", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
b, err := server.buckets.GetBucket(ctx, bucket, project.UUID)
|
|
|
|
if err != nil {
|
2023-04-13 13:04:07 +01:00
|
|
|
if buckets.ErrBucketNotFound.Has(err) {
|
2023-04-03 09:22:22 +01:00
|
|
|
sendJSONError(w, "bucket does not exist", "", http.StatusNotFound)
|
2021-11-12 20:48:29 +00:00
|
|
|
} else {
|
|
|
|
sendJSONError(w, "unable to check bucket", err.Error(), http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := json.Marshal(b)
|
|
|
|
if err != nil {
|
|
|
|
sendJSONError(w, "failed to marshal bucket", err.Error(), http.StatusInternalServerError)
|
|
|
|
} else {
|
|
|
|
sendJSONData(w, http.StatusOK, data)
|
|
|
|
}
|
|
|
|
}
|