Manage Garage Websites from Guichet #19
5 changed files with 172 additions and 15 deletions
129
garage.go
129
garage.go
|
@ -6,7 +6,9 @@ import (
|
|||
"net/http"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"github.com/go-ldap/ldap/v3"
|
||||
"github.com/gorilla/mux"
|
||||
garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
|
||||
)
|
||||
|
||||
|
@ -47,6 +49,67 @@ func grgGetKey(accessKey string) (*garage.KeyInfo, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func grgCreateWebsite(gkey, bucket string) (*garage.BucketInfo, error) {
|
||||
client, ctx := gadmin()
|
||||
|
||||
br := garage.NewCreateBucketRequest()
|
||||
br.SetGlobalAlias(bucket)
|
||||
|
||||
// Create Bucket
|
||||
binfo, _, err := client.BucketApi.CreateBucket(ctx).CreateBucketRequest(*br).Execute()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Allow user's key
|
||||
ar := garage.AllowBucketKeyRequest{
|
||||
BucketId: *binfo.Id,
|
||||
AccessKeyId: gkey,
|
||||
Permissions: *garage.NewAllowBucketKeyRequestPermissions(true, true, true),
|
||||
}
|
||||
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
|
||||
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
|
||||
|
||||
ur := garage.NewUpdateBucketRequest()
|
||||
ur.SetWebsiteAccess(*wr)
|
||||
ur.SetQuotas(*qr)
|
||||
|
||||
binfo, _, err = client.BucketApi.UpdateBucket(ctx, *binfo.Id).UpdateBucketRequest(*ur).Execute()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return updated binfo
|
||||
return binfo, 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)
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
func checkLoginAndS3(w http.ResponseWriter, r *http.Request) (*LoginStatus, *garage.KeyInfo, error) {
|
||||
login := checkLogin(w, r)
|
||||
|
@ -109,18 +172,80 @@ func handleGarageWebsiteList(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func handleGarageWebsiteNew(w http.ResponseWriter, r *http.Request) {
|
||||
_, s3key, err := checkLoginAndS3(w, r)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
// @FIXME we need to return the error to the user
|
||||
tWebsiteNew.Execute(w, nil)
|
||||
return
|
||||
}
|
||||
|
||||
http.Redirect(w, r, "/garage/website/b/" + *binfo.Id, http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
tWebsiteNew.Execute(w, nil)
|
||||
}
|
||||
|
||||
type webInspectView struct {
|
||||
Status *LoginStatus
|
||||
Key *garage.KeyInfo
|
||||
Bucket *garage.BucketInfo
|
||||
IndexDoc string
|
||||
ErrorDoc string
|
||||
MaxObjects int64
|
||||
MaxSize int64
|
||||
UsedSizePct float64
|
||||
}
|
||||
func handleGarageWebsiteInspect(w http.ResponseWriter, r *http.Request) {
|
||||
login, s3key, err := checkLoginAndS3(w, r)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
log.Println(login, s3key)
|
||||
|
||||
bucketId := mux.Vars(r)["bucket"]
|
||||
binfo, err := grgGetBucket(bucketId)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
wc := binfo.GetWebsiteConfig()
|
||||
q := binfo.GetQuotas()
|
||||
|
||||
view := webInspectView {
|
||||
Status: login,
|
||||
Key: s3key,
|
||||
Bucket: binfo,
|
||||
IndexDoc: (&wc).GetIndexDocument(),
|
||||
ErrorDoc: (&wc).GetErrorDocument(),
|
||||
MaxObjects: (&q).GetMaxObjects(),
|
||||
MaxSize: (&q).GetMaxSize(),
|
||||
}
|
||||
|
||||
tWebsiteInspect := getTemplate("garage_website_inspect.html")
|
||||
tWebsiteInspect.Execute(w, nil)
|
||||
tWebsiteInspect.Execute(w, &view)
|
||||
}
|
||||
|
|
22
go.mod
22
go.mod
|
@ -1,6 +1,6 @@
|
|||
module git.deuxfleurs.fr/Deuxfleurs/guichet
|
||||
|
||||
go 1.13
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20230131081355-c965fe7f7dc9
|
||||
|
@ -15,3 +15,23 @@ require (
|
|||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1 // indirect
|
||||
github.com/golang/protobuf v1.4.2 // indirect
|
||||
github.com/gorilla/securecookie v1.1.1 // indirect
|
||||
github.com/json-iterator/go v1.1.10 // indirect
|
||||
github.com/klauspost/cpuid v1.2.3 // indirect
|
||||
github.com/minio/md5-simd v1.1.0 // indirect
|
||||
github.com/minio/sha256-simd v0.1.1 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 // indirect
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
google.golang.org/appengine v1.6.6 // indirect
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/ini.v1 v1.57.0 // indirect
|
||||
)
|
||||
|
|
3
go.sum
3
go.sum
|
@ -134,10 +134,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
|||
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
|
||||
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
|
||||
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
|
||||
|
@ -413,7 +411,6 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
|
|||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
|
||||
|
|
|
@ -12,32 +12,47 @@
|
|||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">ID</th>
|
||||
<td>afa8f0a22b40b1247ccd0affb869b0af5cff980924a20e4b5e0720a44deb8d39</td>
|
||||
<td>{{ .Bucket.Id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">URLs</th>
|
||||
<td>nix.web.deuxfleurs.fr</td>
|
||||
<td>
|
||||
{{ range $alias := .Bucket.GlobalAliases }}
|
||||
{{ if contains $alias "." }}
|
||||
https://{{ $alias }}
|
||||
{{ else }}
|
||||
https://{{ $alias }}.web.deuxfleurs.fr
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Document d'index</th>
|
||||
<td>index.html</td>
|
||||
<td> {{ .IndexDoc }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Document d'erreur</th>
|
||||
<td>error/400.html</td>
|
||||
<td>{{ .ErrorDoc }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Nombre de fichiers</th>
|
||||
<td>488/infini</td>
|
||||
<td>{{ .Bucket.Objects }} / {{ .MaxObjects }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Espace utilisé</th>
|
||||
<td>83216486/infini</td>
|
||||
<td>{{ .Bucket.Bytes }} / {{ .MaxSize }} octets</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h4>Configurer le nom de domaine</h4>
|
||||
|
||||
<p>Le nom de domaine est géré par deuxfleurs, il n'y a rien à configurer.</p>
|
||||
{{ range $alias := .Bucket.GlobalAliases }}
|
||||
{{ if contains $alias "." }}
|
||||
<p> Le nom de domaine {{ $alias }} n'est pas géré par Deuxfleurs, il vous revient donc de configurer la zone DNS. Vous devez ajouter une entrée <code>CNAME garage.deuxfleurs.fr</code> ou <code>ALIAS garage.deuxfleurs.fr</code> auprès de votre hébergeur DNS, qui est souvent aussi le bureau d'enregistrement (eg. Gandi, GoDaddy, BookMyName, etc.).</p>
|
||||
{{ else }}
|
||||
<p> Le nom de domaine https://{{ $alias }}.web.deuxfleurs.fr est fourni par Deuxfleurs, il n'y a pas de configuration à faire.</p>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
{{end}}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<div class="tab-content" id="protocols">
|
||||
<div class="tab-pane fade show active" id="dnsint" role="tabpanel" aria-labelledby="dnsint-tab">
|
||||
<form method="POST" class="mt-4" enctype="multipart/form-data">
|
||||
<form method="POST" class="mt-4">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="bucket">Sous-domaine désiré :</label>
|
||||
|
@ -36,7 +36,7 @@
|
|||
</form>
|
||||
</div>
|
||||
<div class="tab-pane fade show" id="dnsext" role="tabpanel" aria-labelledby="dnsext-tab">
|
||||
<form method="POST" class="mt-4" enctype="multipart/form-data">
|
||||
<form method="POST" class="mt-4">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="bucket2">Votre nom de domaine :</label>
|
||||
|
|
Loading…
Reference in a new issue