diff options
author | Quentin <quentin@dufour.io> | 2023-09-26 06:44:36 +0000 |
---|---|---|
committer | Quentin <quentin@dufour.io> | 2023-09-26 06:44:36 +0000 |
commit | 49d8e81fbea0d4703a33e87a807927169a8060ac (patch) | |
tree | d0b655454d5e13ed2238060fee27fc0d951d64c8 /garage.go | |
parent | 1e75c21b65021da0c3c5a8be9be12114a2327464 (diff) | |
parent | 706ff58a6f6608719feda15075d50f978df39c5b (diff) | |
download | guichet-49d8e81fbea0d4703a33e87a807927169a8060ac.tar.gz guichet-49d8e81fbea0d4703a33e87a807927169a8060ac.zip |
Merge pull request 'An API for Guichet' (#23) from api into main
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/guichet/pulls/23
Diffstat (limited to 'garage.go')
-rw-r--r-- | garage.go | 242 |
1 files changed, 144 insertions, 98 deletions
@@ -2,10 +2,8 @@ package main import ( "context" - "errors" "fmt" garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" - "github.com/go-ldap/ldap/v3" "github.com/gorilla/mux" "log" "net/http" @@ -48,7 +46,7 @@ func grgGetKey(accessKey string) (*garage.KeyInfo, error) { return resp, nil } -func grgCreateWebsite(gkey, bucket string) (*garage.BucketInfo, error) { +func grgCreateBucket(bucket string) (*garage.BucketInfo, error) { client, ctx := gadmin() br := garage.NewCreateBucketRequest() @@ -60,34 +58,40 @@ func grgCreateWebsite(gkey, bucket string) (*garage.BucketInfo, error) { fmt.Printf("%+v\n", err) return nil, err } + return binfo, nil +} + +func grgAllowKeyOnBucket(bid, gkey string) (*garage.BucketInfo, error) { + client, ctx := gadmin() // Allow user's key ar := garage.AllowBucketKeyRequest{ - BucketId: *binfo.Id, + BucketId: bid, AccessKeyId: gkey, Permissions: *garage.NewAllowBucketKeyRequestPermissions(true, true, true), } - binfo, _, err = client.BucketApi.AllowBucketKey(ctx).AllowBucketKeyRequest(ar).Execute() + binfo, _, err := client.BucketApi.AllowBucketKey(ctx).AllowBucketKeyRequest(ar).Execute() if err != nil { fmt.Printf("%+v\n", err) return nil, err } - // Expose website and set quota + return binfo, nil +} + +func allowWebsiteDefault() *garage.UpdateBucketRequestWebsiteAccess { wr := garage.NewUpdateBucketRequestWebsiteAccess() wr.SetEnabled(true) wr.SetIndexDocument("index.html") wr.SetErrorDocument("error.html") - qr := garage.NewUpdateBucketRequestQuotas() - qr.SetMaxSize(1024 * 1024 * 50) // 50MB - qr.SetMaxObjects(10000) //10k objects + return wr +} - ur := garage.NewUpdateBucketRequest() - ur.SetWebsiteAccess(*wr) - ur.SetQuotas(*qr) +func grgUpdateBucket(bid string, ur *garage.UpdateBucketRequest) (*garage.BucketInfo, error) { + client, ctx := gadmin() - binfo, _, err = client.BucketApi.UpdateBucket(ctx, *binfo.Id).UpdateBucketRequest(*ur).Execute() + binfo, _, err := client.BucketApi.UpdateBucket(ctx, bid).UpdateBucketRequest(*ur).Execute() if err != nil { fmt.Printf("%+v\n", err) return nil, err @@ -97,155 +101,197 @@ func grgCreateWebsite(gkey, bucket string) (*garage.BucketInfo, error) { return binfo, nil } -func grgGetBucket(bid string) (*garage.BucketInfo, error) { +func grgAddGlobalAlias(bid, alias string) (*garage.BucketInfo, error) { client, ctx := gadmin() - resp, _, err := client.BucketApi.GetBucketInfo(ctx, bid).Execute() + resp, _, err := client.BucketApi.PutBucketGlobalAlias(ctx).Id(bid).Alias(alias).Execute() if err != nil { - fmt.Printf("%+v\n", err) + 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 checkLoginAndS3(w http.ResponseWriter, r *http.Request) (*LoginStatus, *garage.KeyInfo, error) { - login := checkLogin(w, r) - if login == nil { - return nil, nil, errors.New("LDAP login failed") +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 +} - keyID := login.UserEntry.GetAttributeValue("garage_s3_access_key") - if keyID == "" { - keyPair, err := grgCreateKey(login.Info.Username) - if err != nil { - return login, nil, err - } - modify_request := ldap.NewModifyRequest(login.Info.DN, nil) - modify_request.Replace("garage_s3_access_key", []string{*keyPair.AccessKeyId}) - // @FIXME compatibility feature for bagage (SFTP+webdav) - // you can remove it once bagage will be updated to fetch the key from garage directly - // or when bottin will be able to dynamically fetch it. - modify_request.Replace("garage_s3_secret_key", []string{*keyPair.SecretAccessKey}) - err = login.conn.Modify(modify_request) - return login, keyPair, err +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 } - // Note: we could simply return the login info, but LX asked we do not - // store the secrets in LDAP in the future. - keyPair, err := grgGetKey(keyID) - return login, keyPair, err + return resp, nil } -type keyView struct { - Status *LoginStatus - Key *garage.KeyInfo +func grgGetBucket(bid string) (*garage.BucketInfo, error) { + client, ctx := gadmin() + + resp, _, err := client.BucketApi.GetBucketInfo(ctx, bid).Execute() + if err != nil { + log.Println(err) + return nil, err + } + return resp, nil + } -func handleGarageKey(w http.ResponseWriter, r *http.Request) { - login, s3key, err := checkLoginAndS3(w, r) +func grgDeleteBucket(bid string) error { + client, ctx := gadmin() + + _, err := client.BucketApi.DeleteBucket(ctx, bid).Execute() if err != nil { log.Println(err) + } + return err +} + +// --- Start page rendering functions + +func handleWebsiteConfigure(w http.ResponseWriter, r *http.Request) { + user := RequireUserHtml(w, r) + if user == nil { return } - view := keyView{Status: login, Key: s3key} tKey := getTemplate("garage_key.html") - tKey.Execute(w, &view) + tKey.Execute(w, user) } -type webListView struct { - Status *LoginStatus - Key *garage.KeyInfo -} +func handleWebsiteList(w http.ResponseWriter, r *http.Request) { + user := RequireUserHtml(w, r) + if user == nil { + return + } -func handleGarageWebsiteList(w http.ResponseWriter, r *http.Request) { - login, s3key, err := checkLoginAndS3(w, r) + ctrl, err := NewWebsiteController(user) if err != nil { - log.Println(err) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - view := webListView{Status: login, Key: s3key} - tWebsiteList := getTemplate("garage_website_list.html") - tWebsiteList.Execute(w, &view) + if len(ctrl.PrettyList) > 0 { + http.Redirect(w, r, "/website/inspect/"+ctrl.PrettyList[0], http.StatusFound) + } else { + http.Redirect(w, r, "/website/new", http.StatusFound) + } +} + +type WebsiteNewTpl struct { + Ctrl *WebsiteController + Err error } -func handleGarageWebsiteNew(w http.ResponseWriter, r *http.Request) { - _, s3key, err := checkLoginAndS3(w, r) +func handleWebsiteNew(w http.ResponseWriter, r *http.Request) { + user := RequireUserHtml(w, r) + if user == nil { + return + } + + ctrl, err := NewWebsiteController(user) if err != nil { - log.Println(err) + http.Error(w, err.Error(), http.StatusInternalServerError) return } + tpl := &WebsiteNewTpl{ctrl, nil} + tWebsiteNew := getTemplate("garage_website_new.html") if r.Method == "POST" { r.ParseForm() - log.Println(r.Form) bucket := strings.Join(r.Form["bucket"], "") if bucket == "" { bucket = strings.Join(r.Form["bucket2"], "") } - if bucket == "" { - log.Println("Form empty") - // @FIXME we need to return the error to the user - tWebsiteNew.Execute(w, nil) - return - } - binfo, err := grgCreateWebsite(*s3key.AccessKeyId, bucket) + view, err := ctrl.Create(bucket) if err != nil { - log.Println(err) - // @FIXME we need to return the error to the user - tWebsiteNew.Execute(w, nil) + tpl.Err = err + tWebsiteNew.Execute(w, tpl) return } - http.Redirect(w, r, "/garage/website/b/"+*binfo.Id, http.StatusFound) + http.Redirect(w, r, "/website/inspect/"+view.Name.Pretty, http.StatusFound) return } - tWebsiteNew.Execute(w, nil) + tWebsiteNew.Execute(w, tpl) } -type webInspectView struct { - Status *LoginStatus - Key *garage.KeyInfo - Bucket *garage.BucketInfo - IndexDoc string - ErrorDoc string - MaxObjects int64 - MaxSize int64 - UsedSizePct float64 +type WebsiteInspectTpl struct { + Describe *WebsiteDescribe + View *WebsiteView + Err error } -func handleGarageWebsiteInspect(w http.ResponseWriter, r *http.Request) { - login, s3key, err := checkLoginAndS3(w, r) - if err != nil { - log.Println(err) +func handleWebsiteInspect(w http.ResponseWriter, r *http.Request) { + var processErr error + + user := RequireUserHtml(w, r) + if user == nil { return } - bucketId := mux.Vars(r)["bucket"] - binfo, err := grgGetBucket(bucketId) + ctrl, err := NewWebsiteController(user) if err != nil { - log.Println(err) + http.Error(w, err.Error(), http.StatusInternalServerError) return } - wc := binfo.GetWebsiteConfig() - q := binfo.GetQuotas() + bucketName := mux.Vars(r)["bucket"] - view := webInspectView{ - Status: login, - Key: s3key, - Bucket: binfo, - IndexDoc: (&wc).GetIndexDocument(), - ErrorDoc: (&wc).GetErrorDocument(), - MaxObjects: (&q).GetMaxObjects(), - MaxSize: (&q).GetMaxSize(), + if r.Method == "POST" { + r.ParseForm() + action := strings.Join(r.Form["action"], "") + switch action { + case "increase_quota": + _, processErr = ctrl.Patch(bucketName, &WebsitePatch{Size: &user.Quota.WebsiteSizeBursted}) + case "delete_bucket": + processErr = ctrl.Delete(bucketName) + http.Redirect(w, r, "/website", http.StatusFound) + return + default: + processErr = fmt.Errorf("Unknown action") + } + + } + + view, err := ctrl.Inspect(bucketName) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return } + describe, err := ctrl.Describe() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + tpl := &WebsiteInspectTpl{describe, view, processErr} + tWebsiteInspect := getTemplate("garage_website_inspect.html") - tWebsiteInspect.Execute(w, &view) + tWebsiteInspect.Execute(w, &tpl) } |