aboutsummaryrefslogblamecommitdiff
path: root/api.go
blob: 7d9c2cd8e197e6c0ac44aab04e70907cdb07cf01 (plain) (tree)
1
2
3
4
5
6
7
8
9
10



                   
                
                       
                                                                     
                                

                  

 


















                                  
                                                                    
        



















                                                                                                    


                                                              






                                                                      




                                      





























                                                                                      
        








                                                                  

                                
                                                                                 

                      
 

























                                                                                                                                                 
 
                                                      
 
                      










                                                                                                                     
                         

                                     
                           

                                         
                           

                                         
                           
 

                              
 









                                                                                               
 
package main

import (
	//"context"
	"errors"
	"encoding/json"
	garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
	"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 handleAPIGarageBucket(w http.ResponseWriter, r *http.Request) {
	
	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) {
	user := RequireUserApi(w, r)
	if user == nil {
		return nil, errors.New("Unable to fetch user")
	}

	// 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()
	if err != nil {
		return nil, err
	}

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
	}

	// 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
			}
		}
	}

	// 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)
}

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)
}