aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2023-09-15 18:25:37 +0200
committerQuentin Dufour <quentin@deuxfleurs.fr>2023-09-15 18:25:37 +0200
commit5b246ec86bc3eee768da2347f031b349d1e1553d (patch)
tree4f79ff571729b7a61f8f0aac2d5819e48a8bcb66
parente876bdd6632e0f00e2973cfba5336128ef00a3ab (diff)
downloadguichet-5b246ec86bc3eee768da2347f031b349d1e1553d.tar.gz
guichet-5b246ec86bc3eee768da2347f031b349d1e1553d.zip
basic logic for switching alias from local/global
-rw-r--r--api.go149
-rw-r--r--garage.go46
-rw-r--r--main.go2
3 files changed, 182 insertions, 15 deletions
diff --git a/api.go b/api.go
index bce9993..1ddb4ea 100644
--- a/api.go
+++ b/api.go
@@ -2,11 +2,12 @@ package main
import (
//"context"
+ "encoding/json"
"errors"
"fmt"
garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
"github.com/go-ldap/ldap/v3"
- //"github.com/gorilla/mux"
+ "github.com/gorilla/mux"
"log"
"net/http"
"strings"
@@ -111,21 +112,132 @@ func checkLoginAndS3API(w http.ResponseWriter, r *http.Request) (*LoginStatus, *
return login, keyPair, err
}
+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 handleAPIGarageBucket(w http.ResponseWriter, r *http.Request) {
- login, s3key, err := checkLoginAndS3API(w, r)
+ br, err := buildBucketRequest(w, r)
+ if err != nil {
+ return
+ }
+
+ if r.Method == http.MethodPatch {
+ patchGarageBucket(w, br)
+ return
+ }
+
+ if r.Method == http.MethodGet {
+ getGarageBucket(w, br)
+ return
+ }
+
+ http.Error(w, "This method is not implemented for this endpoint", http.StatusNotImplemented)
+ return
+}
+
+func buildBucketRequest(w http.ResponseWriter, r *http.Request) (*BucketRequest, error) {
+ _, s3key, err := checkLoginAndS3API(w, r)
+ if err != nil {
+ http.Error(w, "Unable to connect on LDAP", http.StatusUnauthorized)
+ return nil, err
+ }
+
+ // FETCH BUCKET ID by iterating over buckets owned by this key
+ bucketName := mux.Vars(r)["bucket"]
+ var bucketId *string
+ var global *bool
+
+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 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
+
+ // 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)
return
}
- // CHECK PATCH REQUEST
+ // 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
+ }
+ }
+ }
- // READ BODY JSON
+ // CHECK IF QUOTA MUST BE ADDED TO THIS BUCKET
- // VALIDATE OBJECT
- // --- bucket query parameter ---
- // 1. bucket must be owned by the key with owner permission, otherwise throw "unauthorized" (401)
- // 2. must not end with deuxfleurs.fr or deuxfleurs.org, otherwise throw "forbidden" (403)
+ // VALIDATE IT
// --- global ---
// 1. can be true, false, or nil (use pointers)
// 2. if nil do nothing
@@ -137,17 +249,28 @@ func handleAPIGarageBucket(w http.ResponseWriter, r *http.Request) {
// --- 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
- // Add an alias
+ // DO: Add an alias
// IF BODY.QUOTA.SIZE is not NONE
- // Change quota
+ // DO: Change quota
// IF BODY.QUOTA.FILE is not NONE
- // Change quota
+ // DO: Change quota
- log.Println(login, s3key)
+ getGarageBucket(w, br)
+}
- 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)
+ return
+ }
+
+ // BUILD A VIEW
+ log.Println(bucket)
}
diff --git a/garage.go b/garage.go
index 61d1b93..db35366 100644
--- a/garage.go
+++ b/garage.go
@@ -97,12 +97,56 @@ func grgCreateWebsite(gkey, bucket string) (*garage.BucketInfo, error) {
return binfo, nil
}
+func grgAddGlobalAlias(bid, alias string) (*garage.BucketInfo, error) {
+ client, ctx := gadmin()
+
+ resp, _, err := client.BucketApi.PutBucketGlobalAlias(ctx).Id(bid).Alias(alias).Execute()
+ if err != nil {
+ log.Println(err)
+ return nil, err
+ }
+ return resp, nil
+}
+
+func grgAddLocalAlias(bid, key, alias string) (*garage.BucketInfo, error) {
+ client, ctx := gadmin()
+
+ resp, _, err := client.BucketApi.PutBucketLocalAlias(ctx).Id(bid).AccessKeyId(key).Alias(alias).Execute()
+ if err != nil {
+ log.Println(err)
+ return nil, err
+ }
+ return resp, nil
+}
+
+func grgDelGlobalAlias(bid, alias string) (*garage.BucketInfo, error) {
+ client, ctx := gadmin()
+
+ resp, _, err := client.BucketApi.DeleteBucketGlobalAlias(ctx).Id(bid).Alias(alias).Execute()
+ if err != nil {
+ log.Println(err)
+ return nil, err
+ }
+ return resp, nil
+}
+
+func grgDelLocalAlias(bid, key, alias string) (*garage.BucketInfo, error) {
+ client, ctx := gadmin()
+
+ resp, _, err := client.BucketApi.DeleteBucketLocalAlias(ctx).Id(bid).AccessKeyId(key).Alias(alias).Execute()
+ if err != nil {
+ log.Println(err)
+ return nil, err
+ }
+ return resp, nil
+}
+
func grgGetBucket(bid string) (*garage.BucketInfo, error) {
client, ctx := gadmin()
resp, _, err := client.BucketApi.GetBucketInfo(ctx, bid).Execute()
if err != nil {
- fmt.Printf("%+v\n", err)
+ log.Println(err)
return nil, err
}
return resp, nil
diff --git a/main.go b/main.go
index 1402ff2..8bfb2f8 100644
--- a/main.go
+++ b/main.go
@@ -130,7 +130,7 @@ func main() {
r.HandleFunc("/", handleHome)
r.HandleFunc("/logout", handleLogout)
- r.HandleFunc("/api/unstable/garage/bucket/{b}", handleAPIGarageBucket)
+ r.HandleFunc("/api/unstable/garage/bucket/{bucket}", handleAPIGarageBucket)
r.HandleFunc("/profile", handleProfile)
r.HandleFunc("/passwd", handlePasswd)