aboutsummaryrefslogtreecommitdiff
path: root/api.go
diff options
context:
space:
mode:
Diffstat (limited to 'api.go')
-rw-r--r--api.go212
1 files changed, 77 insertions, 135 deletions
diff --git a/api.go b/api.go
index fd6df93..c804276 100644
--- a/api.go
+++ b/api.go
@@ -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
}