diff options
Diffstat (limited to 'api.go')
-rw-r--r-- | api.go | 212 |
1 files changed, 77 insertions, 135 deletions
@@ -1,48 +1,29 @@ package main import ( - //"context" "errors" "encoding/json" - garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" + "fmt" "github.com/gorilla/mux" - "log" "net/http" ) -type ApiQuotaView struct { - files *uint64 - size *uint64 -} - -type ApiBucketView struct { - global *bool - max *ApiQuotaView - used *ApiQuotaView -} - -type BucketRequest struct { - s3key *garage.KeyInfo - bucketName string - bucketId string - global bool - http *http.Request -} +func handleAPIWebsiteList(w http.ResponseWriter, r *http.Request) { + user := RequireUserApi(w, r) -func handleAPIWebsite(w http.ResponseWriter, r *http.Request) { - - br, err := buildBucketRequest(w, r) - if err != nil { - return + if user == nil { + return } - if r.Method == http.MethodPatch { - patchGarageBucket(w, br) + ctrl, err := NewWebsiteController(user) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) return } if r.Method == http.MethodGet { - getGarageBucket(w, br) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(ctrl.Describe()) return } @@ -50,131 +31,92 @@ func handleAPIWebsite(w http.ResponseWriter, r *http.Request) { return } -func buildBucketRequest(w http.ResponseWriter, r *http.Request) (*BucketRequest, error) { +func handleAPIWebsiteInspect(w http.ResponseWriter, r *http.Request) { user := RequireUserApi(w, r) + if user == nil { - return nil, errors.New("Unable to fetch user") + return } - // FETCH BUCKET ID by iterating over buckets owned by this key bucketName := mux.Vars(r)["bucket"] - var bucketId *string - var global *bool - - s3key, err := user.S3KeyInfo() + ctrl, err := NewWebsiteController(user) if err != nil { - return nil, err + http.Error(w, err.Error(), http.StatusInternalServerError) + return } -findBucketIdLoop: - for _, bucket := range s3key.Buckets { - for _, localAlias := range bucket.LocalAliases { - if localAlias == bucketName { - bucketId = bucket.Id - *global = false - break findBucketIdLoop - } - } - for _, globalAlias := range bucket.GlobalAliases { - if globalAlias == bucketName { - bucketId = bucket.Id - *global = true - break findBucketIdLoop - } + if r.Method == http.MethodGet { + view, err := ctrl.Inspect(bucketName) + if errors.Is(err, ErrWebsiteNotFound) { + http.Error(w, err.Error(), http.StatusNotFound) + return + } else if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(view) + return } - if bucketId == nil || global == nil { - http.Error(w, "Bucket not found in this account", http.StatusNotFound) - return nil, errors.New("Unable to fetch bucket ID") - } - - return &BucketRequest{ - s3key: s3key, - bucketName: bucketName, - bucketId: *bucketId, - global: *global, - http: r, - }, nil - -} - -func patchGarageBucket(w http.ResponseWriter, br *BucketRequest) { - var err error + if r.Method == http.MethodPost { + view, err := ctrl.Create(bucketName) + if errors.Is(err, ErrEmptyBucketName) { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } else if errors.Is(err, ErrWebsiteQuotaReached) { + http.Error(w, err.Error(), http.StatusForbidden) + return + } else if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } - // DECODE BODY - var queuedChange ApiBucketView - decoder := json.NewDecoder(br.http.Body) - err = decoder.Decode(&queuedChange) - if err != nil { - log.Println(err) - http.Error(w, "Unable to decode the body", http.StatusBadRequest) + w.WriteHeader(http.StatusCreated) + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(view) return } - // SET THE GLOBAL FLAG - if queuedChange.global != nil { - if *queuedChange.global && !br.global { - _, err = grgAddGlobalAlias(br.bucketId, br.bucketName) - if err != nil { - http.Error(w, "Unable to add the requested name as global alias for this bucket", http.StatusInternalServerError) - return - } - _, err = grgDelLocalAlias(br.bucketId, *br.s3key.AccessKeyId, br.bucketName) - if err != nil { - http.Error(w, "Unable to remove the local alias for this bucket", http.StatusInternalServerError) - return - } - } else if !*queuedChange.global && br.global { - grgAddLocalAlias(br.bucketId, *br.s3key.AccessKeyId, br.bucketName) - if err != nil { - http.Error(w, "Unable to add the requested name as local alias for this bucket", http.StatusInternalServerError) - return - } - grgDelGlobalAlias(br.bucketId, br.bucketName) - if err != nil { - http.Error(w, "Unable to remove the global alias for this bucket", http.StatusInternalServerError) - return - } + if r.Method == http.MethodPatch { + var patch WebsitePatch + err := json.NewDecoder(r.Body).Decode(&patch) + if err != nil { + http.Error(w, errors.Join(fmt.Errorf("Can't parse the request body as a website patch JSON"), err).Error(), http.StatusBadRequest) + return } - } - - // CHECK IF QUOTA MUST BE ADDED TO THIS BUCKET - - // VALIDATE IT - // --- global --- - // 1. can be true, false, or nil (use pointers) - // 2. if nil do nothing - // 3. if false, throw "not yet implemented" (501) - // 4. if true, check that the bucket name does not exist yet in the global namespace, throw "forbidden" (403) - // --- quota.size --- - // 1. if no quota on the bucket + this field is none, set to 50MB - // 2. if lower than 50MB, set to 50MB. If higher than 200MB, set to 200MB - // --- quota.files --- - // 1. if no quota on the bucket + this field is none, set to 10k - // 2. if lower than 10k, set to 10k. If higher than 40k, set to 40k - // READ BODY JSON - - // IF BODY.GLOBAL is not NONE - // DO: Add an alias - // IF BODY.QUOTA.SIZE is not NONE - // DO: Change quota - - // IF BODY.QUOTA.FILE is not NONE - // DO: Change quota - - getGarageBucket(w, br) -} + view, err := ctrl.Patch(bucketName, &patch) + if errors.Is(err, ErrWebsiteNotFound) { + http.Error(w, err.Error(), http.StatusNotFound) + return + } else if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(view) + return + } -func getGarageBucket(w http.ResponseWriter, br *BucketRequest) { - // FETCH AN UPDATED BUCKET VIEW - bucket, err := grgGetBucket(br.bucketId) - if err != nil { - http.Error(w, "Unable to fetch bucket details", http.StatusInternalServerError) + if r.Method == http.MethodDelete { + err := ctrl.Delete(bucketName) + if errors.Is(err, ErrEmptyBucketName) || errors.Is(err, ErrBucketDeleteNotEmpty) || errors.Is(err, ErrBucketDeleteUnfinishedUpload) { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } else if errors.Is(err, ErrWebsiteNotFound) { + http.Error(w, err.Error(), http.StatusNotFound) + return + } else if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusNoContent) return + } - // BUILD A VIEW - log.Println(bucket) + http.Error(w, "This method is not implemented for this endpoint", http.StatusNotImplemented) + return } |