satellite/admin: change returned data to be json encoded
Change-Id: I239779fe54328fe854fcbdd71f7906875cd76635
This commit is contained in:
parent
f804f03b1f
commit
d654ab5fa0
@ -3,7 +3,30 @@
|
||||
|
||||
package admin
|
||||
|
||||
import "github.com/zeebo/errs"
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/zeebo/errs"
|
||||
)
|
||||
|
||||
// Error is default error class for admin package.
|
||||
var Error = errs.Class("admin")
|
||||
|
||||
func httpJSONError(w http.ResponseWriter, error, detail string, statusCode int) {
|
||||
errStr := struct {
|
||||
Error string `json:"error"`
|
||||
Detail string `json:"detail"`
|
||||
}{
|
||||
Error: error,
|
||||
Detail: detail,
|
||||
}
|
||||
byt, err := json.Marshal(errStr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(statusCode)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write(byt) // any error here entitles a client side disconnect or similar, which we do not care about.
|
||||
}
|
||||
|
@ -22,7 +22,8 @@ func (server *Server) addCoupon(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to read body",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -35,21 +36,26 @@ func (server *Server) addCoupon(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(body, &input)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to unmarshal request: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "failed to unmarshal request",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
switch {
|
||||
case input.Duration == 0:
|
||||
http.Error(w, "Duration is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "Duration is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
case input.Amount == 0:
|
||||
http.Error(w, "Amount is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "Amount is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
case input.Description == "":
|
||||
http.Error(w, "Description is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "Description is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
case input.UserID.IsZero():
|
||||
http.Error(w, "UserID is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "UserID is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -60,13 +66,15 @@ func (server *Server) addCoupon(w http.ResponseWriter, r *http.Request) {
|
||||
Description: input.Description,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to insert coupon: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to insert coupon",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.Marshal(coupon.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "json encoding failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -80,28 +88,33 @@ func (server *Server) couponInfo(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, ok := vars["couponid"]
|
||||
if !ok {
|
||||
http.Error(w, "couponId missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "couponId missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
couponID, err := uuid.FromString(id)
|
||||
if err != nil {
|
||||
http.Error(w, "invalid couponId", http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid couponId",
|
||||
"", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
coupon, err := server.db.StripeCoinPayments().Coupons().Get(ctx, couponID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
http.Error(w, fmt.Sprintf("coupon with id %q not found", couponID), http.StatusNotFound)
|
||||
httpJSONError(w, fmt.Sprintf("coupon with id %q not found", couponID),
|
||||
"", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get coupon %q: %v", couponID, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get coupon",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.Marshal(coupon)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "json encoding failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -115,19 +128,22 @@ func (server *Server) deleteCoupon(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
UUIDString, ok := vars["couponid"]
|
||||
if !ok {
|
||||
http.Error(w, "couponid missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "couponid missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
couponID, err := uuid.FromString(UUIDString)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid couponid: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid couponid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.db.StripeCoinPayments().Coupons().Delete(ctx, couponID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to delete coupon: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to delete coupon",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -29,31 +29,36 @@ func (server *Server) getProjectLimit(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
projectUUIDString, ok := vars["project"]
|
||||
if !ok {
|
||||
http.Error(w, "project-uuid missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "project-uuid missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
projectUUID, err := uuid.FromString(projectUUIDString)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid project-uuid: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid project-uuid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
usagelimit, err := server.db.ProjectAccounting().GetProjectStorageLimit(ctx, projectUUID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get usage limit: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get usage limit",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bandwidthlimit, err := server.db.ProjectAccounting().GetProjectBandwidthLimit(ctx, projectUUID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get bandwidth limit: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get bandwidth limit",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
project, err := server.db.Console().Projects().Get(ctx, projectUUID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get project: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get project",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -82,7 +87,8 @@ func (server *Server) getProjectLimit(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
data, err := json.Marshal(output)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "json encoding failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -96,13 +102,15 @@ func (server *Server) putProjectLimit(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
projectUUIDString, ok := vars["project"]
|
||||
if !ok {
|
||||
http.Error(w, "project-uuid missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "project-uuid missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
projectUUID, err := uuid.FromString(projectUUIDString)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid project-uuid: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid project-uuid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -114,65 +122,75 @@ func (server *Server) putProjectLimit(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid form: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid form",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
decoder := schema.NewDecoder()
|
||||
err = decoder.Decode(&arguments, r.Form)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid arguments: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid arguments",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if arguments.Usage != nil {
|
||||
if *arguments.Usage < 0 {
|
||||
http.Error(w, fmt.Sprintf("negative usage: %v", arguments.Usage), http.StatusBadRequest)
|
||||
httpJSONError(w, "negative usage",
|
||||
fmt.Sprintf("%v", arguments.Usage), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.db.ProjectAccounting().UpdateProjectUsageLimit(ctx, projectUUID, *arguments.Usage)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to update usage: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to update usage",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if arguments.Bandwidth != nil {
|
||||
if *arguments.Bandwidth < 0 {
|
||||
http.Error(w, fmt.Sprintf("negative bandwidth: %v", arguments.Usage), http.StatusBadRequest)
|
||||
httpJSONError(w, "negative bandwidth",
|
||||
fmt.Sprintf("%v", arguments.Usage), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.db.ProjectAccounting().UpdateProjectBandwidthLimit(ctx, projectUUID, *arguments.Bandwidth)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to update bandwidth: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to update bandwidth",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if arguments.Rate != nil {
|
||||
if *arguments.Rate < 0 {
|
||||
http.Error(w, fmt.Sprintf("negative rate: %v", arguments.Rate), http.StatusBadRequest)
|
||||
httpJSONError(w, "negative rate",
|
||||
fmt.Sprintf("%v", arguments.Rate), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.db.Console().Projects().UpdateRateLimit(ctx, projectUUID, *arguments.Rate)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to update rate: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to update rate",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if arguments.Buckets != nil {
|
||||
if *arguments.Buckets < 0 {
|
||||
http.Error(w, fmt.Sprintf("negative bucket count: %v", arguments.Buckets), http.StatusBadRequest)
|
||||
httpJSONError(w, "negative bucket coun",
|
||||
fmt.Sprintf("t: %v", arguments.Buckets), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.db.Console().Projects().UpdateBucketLimit(ctx, projectUUID, *arguments.Buckets)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to update bucket limit: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to update bucket limit",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -183,7 +201,8 @@ func (server *Server) addProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to read body",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -198,17 +217,20 @@ func (server *Server) addProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(body, &input)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to unmarshal request: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "failed to unmarshal request",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if input.OwnerID.IsZero() {
|
||||
http.Error(w, "OwnerID is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "OwnerID is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if input.ProjectName == "" {
|
||||
http.Error(w, "ProjectName is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "ProjectName is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -217,20 +239,23 @@ func (server *Server) addProject(w http.ResponseWriter, r *http.Request) {
|
||||
OwnerID: input.OwnerID,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to insert project: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to insert project",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = server.db.Console().ProjectMembers().Insert(ctx, project.OwnerID, project.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to insert project member: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to insert project member",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
output.ProjectID = project.ID
|
||||
data, err := json.Marshal(output)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "json encoding failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -244,29 +269,34 @@ func (server *Server) renameProject(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
projectUUIDString, ok := vars["project"]
|
||||
if !ok {
|
||||
http.Error(w, "project-uuid missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "project-uuid missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
projectUUID, err := uuid.FromString(projectUUIDString)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid project-uuid: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid project-uuid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
project, err := server.db.Console().Projects().Get(ctx, projectUUID)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
http.Error(w, "project with specified uuid does not exist", http.StatusBadRequest)
|
||||
httpJSONError(w, "project with specified uuid does not exist",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error getting project: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "error getting project",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "ailed to read body",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -277,12 +307,14 @@ func (server *Server) renameProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(body, &input)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to unmarshal request: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "failed to unmarshal request",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if input.ProjectName == "" {
|
||||
http.Error(w, "ProjectName is not set", http.StatusBadRequest)
|
||||
httpJSONError(w, "ProjectName is not set",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -291,7 +323,8 @@ func (server *Server) renameProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = server.db.Console().Projects().Update(ctx, project)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("error renaming project: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "error renaming project",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -302,38 +335,46 @@ func (server *Server) deleteProject(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
projectUUIDString, ok := vars["project"]
|
||||
if !ok {
|
||||
http.Error(w, "project-uuid missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "project-uuid missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
projectUUID, err := uuid.FromString(projectUUIDString)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid project-uuid: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid project-uuid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, fmt.Sprintf("invalid form: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "invalid form",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
buckets, err := server.db.Buckets().ListBuckets(ctx, projectUUID, storj.BucketListOptions{Limit: 1, Direction: storj.Forward}, macaroon.AllowedBuckets{All: true})
|
||||
options := storj.BucketListOptions{Limit: 1, Direction: storj.Forward}
|
||||
buckets, err := server.db.Buckets().ListBuckets(ctx, projectUUID, options, macaroon.AllowedBuckets{All: true})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to list buckets: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to list buckets",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if len(buckets.Items) > 0 {
|
||||
http.Error(w, fmt.Sprintf("buckets still exist: %v", bucketNames(buckets.Items)), http.StatusConflict)
|
||||
httpJSONError(w, "buckets still exist",
|
||||
fmt.Sprintf("%v", bucketNames(buckets.Items)), http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
keys, err := server.db.Console().APIKeys().GetPagedByProjectID(ctx, projectUUID, console.APIKeyCursor{Limit: 1, Page: 1})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to list api-keys: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to list api-keys",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if keys.TotalCount > 0 {
|
||||
http.Error(w, fmt.Sprintf("api-keys still exist: count %v", keys.TotalCount), http.StatusConflict)
|
||||
httpJSONError(w, "api-keys still exist",
|
||||
fmt.Sprintf("count %d", keys.TotalCount), http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
@ -343,18 +384,21 @@ func (server *Server) deleteProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
currentUsage, err := server.db.ProjectAccounting().GetProjectTotal(ctx, projectUUID, firstOfMonth, time.Now())
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to list project usage: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to list project usage",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if currentUsage.Storage > 0 || currentUsage.Egress > 0 || currentUsage.ObjectCount > 0 {
|
||||
http.Error(w, "usage for current month exists", http.StatusConflict)
|
||||
httpJSONError(w, "usage for current month exists",
|
||||
"", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
// if usage of last month exist, make sure to look for billing records
|
||||
lastMonthUsage, err := server.db.ProjectAccounting().GetProjectTotal(ctx, projectUUID, firstOfMonth.AddDate(0, -1, 0), firstOfMonth.AddDate(0, 0, -1))
|
||||
if err != nil {
|
||||
http.Error(w, "error getting project totals", http.StatusInternalServerError)
|
||||
httpJSONError(w, "error getting project totals",
|
||||
"", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -364,26 +408,31 @@ func (server *Server) deleteProject(w http.ResponseWriter, r *http.Request) {
|
||||
case stripecoinpayments.ErrProjectRecordExists:
|
||||
record, err := server.db.StripeCoinPayments().ProjectRecords().Get(ctx, projectUUID, firstOfMonth.AddDate(0, -1, 0), firstOfMonth.Add(-time.Hour))
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to get project records: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to get project records",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
// state = 0 means unapplied and not invoiced yet.
|
||||
if record.State == 0 {
|
||||
http.Error(w, "unapplied project invoice record exist", http.StatusConflict)
|
||||
httpJSONError(w, "unapplied project invoice record exist",
|
||||
"", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
case nil:
|
||||
http.Error(w, "usage for last month exist, but is not billed yet", http.StatusConflict)
|
||||
httpJSONError(w, "usage for last month exist, but is not billed yet",
|
||||
"", http.StatusConflict)
|
||||
return
|
||||
default:
|
||||
http.Error(w, fmt.Sprintf("unable to get project records: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to get project records",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = server.db.Console().Projects().Delete(ctx, projectUUID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to delete project: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to delete project",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ func TestDeleteProjectWithUsageCurrentMonth(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
responseBody, err := ioutil.ReadAll(response.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "usage for current month exists\n", string(responseBody))
|
||||
require.Equal(t, "{\"error\":\"usage for current month exists\",\"detail\":\"\"}", string(responseBody))
|
||||
require.NoError(t, response.Body.Close())
|
||||
require.Equal(t, http.StatusConflict, response.StatusCode)
|
||||
})
|
||||
@ -401,7 +401,7 @@ func TestDeleteProjectWithUsagePreviousMonth(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
responseBody, err := ioutil.ReadAll(response.Body)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "usage for last month exist, but is not billed yet\n", string(responseBody))
|
||||
require.Equal(t, "{\"error\":\"usage for last month exist, but is not billed yet\",\"detail\":\"\"}", string(responseBody))
|
||||
require.NoError(t, response.Body.Close())
|
||||
require.Equal(t, http.StatusConflict, response.StatusCode)
|
||||
})
|
||||
|
@ -24,7 +24,8 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to read body",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -32,7 +33,8 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(body, &input)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to unmarshal request: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "failed to unmarshal request",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -47,23 +49,27 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
existingUser, err := server.db.Console().Users().GetByEmail(ctx, input.Email)
|
||||
if err != nil && !errors.Is(sql.ErrNoRows, err) {
|
||||
http.Error(w, fmt.Sprintf("failed to check for user email %q: %v", input.Email, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to check for user email",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if existingUser != nil {
|
||||
http.Error(w, fmt.Sprintf("user with email already exists %s", input.Email), http.StatusConflict)
|
||||
httpJSONError(w, fmt.Sprintf("user with email already exists %s", input.Email),
|
||||
"", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(input.Password), 0)
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to save password hash", http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to save password hash",
|
||||
"", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
userID, err := uuid.New()
|
||||
if err != nil {
|
||||
http.Error(w, "Unable to create UUID", http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to create UUID",
|
||||
"", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -75,7 +81,8 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = user.IsValid()
|
||||
if err != nil {
|
||||
http.Error(w, "User data is not valid", http.StatusBadRequest)
|
||||
httpJSONError(w, "user data is not valid",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -87,13 +94,15 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
PasswordHash: hash,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to insert user: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to insert user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = server.payments.Setup(ctx, newuser.ID, newuser.Email)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to create payment account for user: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to create payment account for user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -102,13 +111,15 @@ func (server *Server) addUser(w http.ResponseWriter, r *http.Request) {
|
||||
newuser.PasswordHash = nil
|
||||
err = server.db.Console().Users().Update(ctx, newuser)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to activate user: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to activate user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := json.Marshal(newuser)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "json encoding failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -122,30 +133,35 @@ func (server *Server) userInfo(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
userEmail, ok := vars["useremail"]
|
||||
if !ok {
|
||||
http.Error(w, "user-email missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "user-email missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := server.db.Console().Users().GetByEmail(ctx, userEmail)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
http.Error(w, fmt.Sprintf("user with email %q not found", userEmail), http.StatusNotFound)
|
||||
httpJSONError(w, fmt.Sprintf("user with email %q not found", userEmail),
|
||||
"", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get user %q: %v", userEmail, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
user.PasswordHash = nil
|
||||
|
||||
projects, err := server.db.Console().Projects().GetByUserID(ctx, user.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get user projects %q: %v", userEmail, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get user projects",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
coupons, err := server.db.StripeCoinPayments().Coupons().ListByUserID(ctx, user.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get user coupons %q: %v", userEmail, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get user coupons",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -184,7 +200,8 @@ func (server *Server) userInfo(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
data, err := json.Marshal(output)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("json encoding failed: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "json encoding failed",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -198,23 +215,27 @@ func (server *Server) updateUser(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
userEmail, ok := vars["useremail"]
|
||||
if !ok {
|
||||
http.Error(w, "user-email missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "user-email missing",
|
||||
"", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := server.db.Console().Users().GetByEmail(ctx, userEmail)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
http.Error(w, fmt.Sprintf("user with email %q not found", userEmail), http.StatusNotFound)
|
||||
httpJSONError(w, fmt.Sprintf("user with email %q not found", userEmail),
|
||||
"", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get user %q: %v", userEmail, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to read body",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@ -222,7 +243,8 @@ func (server *Server) updateUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = json.Unmarshal(body, &input)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to unmarshal request: %v", err), http.StatusBadRequest)
|
||||
httpJSONError(w, "failed to unmarshal request",
|
||||
err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
@ -244,7 +266,8 @@ func (server *Server) updateUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = server.db.Console().Users().Update(ctx, user)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to update user: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to update user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -255,24 +278,27 @@ func (server *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
userEmail, ok := vars["useremail"]
|
||||
if !ok {
|
||||
http.Error(w, "user-email missing", http.StatusBadRequest)
|
||||
httpJSONError(w, "user-email missing", "", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := server.db.Console().Users().GetByEmail(ctx, userEmail)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
http.Error(w, fmt.Sprintf("user with email %q not found", userEmail), http.StatusNotFound)
|
||||
httpJSONError(w, fmt.Sprintf("user with email %q not found", userEmail),
|
||||
"", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to get user %q: %v", userEmail, err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "failed to get user details",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure user has no own projects any longer
|
||||
projects, err := server.db.Console().Projects().GetByUserID(ctx, user.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to list buckets: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to list buckets",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if len(projects) > 0 {
|
||||
@ -283,7 +309,8 @@ func (server *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
// Delete memberships in foreign projects
|
||||
members, err := server.db.Console().ProjectMembers().GetByMemberID(ctx, user.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to search for user project memberships: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to search for user project memberships",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if len(members) > 0 {
|
||||
@ -299,7 +326,8 @@ func (server *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
// ensure no unpaid invoices exist.
|
||||
invoices, err := server.payments.Invoices().List(ctx, user.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to list user invoices: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to list user invoices",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if len(invoices) > 0 {
|
||||
@ -313,11 +341,13 @@ func (server *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
hasItems, err := server.payments.Invoices().CheckPendingItems(ctx, user.ID)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to list pending invoice items: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to list pending invoice items",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if hasItems {
|
||||
http.Error(w, "user has pending invoice items", http.StatusConflict)
|
||||
httpJSONError(w, "user has pending invoice items",
|
||||
"", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
|
||||
@ -331,7 +361,8 @@ func (server *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
err = server.db.Console().Users().Update(ctx, userInfo)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("unable to delete user: %v", err), http.StatusInternalServerError)
|
||||
httpJSONError(w, "unable to delete user",
|
||||
err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user