aboutsummaryrefslogtreecommitdiff
path: root/website.go
diff options
context:
space:
mode:
Diffstat (limited to 'website.go')
-rw-r--r--website.go211
1 files changed, 211 insertions, 0 deletions
diff --git a/website.go b/website.go
new file mode 100644
index 0000000..c06ccbc
--- /dev/null
+++ b/website.go
@@ -0,0 +1,211 @@
+package main
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+ garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
+)
+
+var (
+ ErrWebsiteNotFound = fmt.Errorf("Website not found")
+ ErrFetchBucketInfo = fmt.Errorf("Failed to fetch bucket information")
+ ErrWebsiteQuotaReached = fmt.Errorf("Can't create additional websites, quota reached")
+ ErrEmptyBucketName = fmt.Errorf("You can't create a website with an empty name")
+ ErrCantCreateBucket = fmt.Errorf("Can't create this bucket. Maybe another bucket already exists with this name or you have an invalid character")
+ ErrCantAllowKey = fmt.Errorf("Can't allow given key on the target bucket")
+ ErrCantConfigureBucket = fmt.Errorf("Unable to configure the bucket (activating website, adding quotas, etc.)")
+)
+
+type QuotaStat struct {
+ Current int64
+ Max int64
+ Ratio float64
+ Burstable bool
+}
+func NewQuotaStat(current, max int64, burstable bool) QuotaStat {
+ return QuotaStat {
+ Current: current,
+ Max: max,
+ Ratio: float64(current) / float64(max),
+ Burstable: burstable,
+ }
+}
+func (q *QuotaStat) IsFull() bool {
+ return q.Current >= q.Max
+}
+func (q *QuotaStat) Percent() int64 {
+ return int64(q.Ratio * 100)
+}
+
+func (q *QuotaStat) PrettyCurrent() string {
+ return prettyValue(q.Current)
+}
+func (q *QuotaStat) PrettyMax() string {
+ return prettyValue(q.Max)
+}
+
+func prettyValue(v int64) string {
+ if v < 1024 {
+ return fmt.Sprintf("%d octets", v)
+ }
+ v = v / 1024
+ if v < 1024 {
+ return fmt.Sprintf("%d kio", v)
+ }
+ v = v / 1024
+ if v < 1024 {
+ return fmt.Sprintf("%d Mio", v)
+ }
+ v = v / 1024
+ if v < 1024 {
+ return fmt.Sprintf("%d Gio", v)
+ }
+ v = v / 1024
+ return fmt.Sprintf("%d Tio", v)
+}
+
+type WebsiteId struct {
+ Pretty string
+ Internal string
+ Alt []string
+ Expanded bool
+ Url string
+
+}
+func NewWebsiteId(id string, aliases []string) *WebsiteId {
+ pretty := id
+ var alt []string
+ if len(aliases) > 0 {
+ pretty = aliases[0]
+ alt = aliases[1:]
+ }
+ expanded := strings.Contains(pretty, ".")
+
+ url := pretty
+ if !expanded {
+ url = fmt.Sprintf("%s.web.deuxfleurs.fr", pretty)
+ }
+
+ return &WebsiteId { pretty, id, alt, expanded, url }
+}
+func NewWebsiteIdFromBucketInfo(binfo *garage.BucketInfo) *WebsiteId {
+ return NewWebsiteId(*binfo.Id, binfo.GlobalAliases)
+}
+
+type WebsiteController struct {
+ User *LoggedUser
+ WebsiteIdx map[string]*WebsiteId
+ PrettyList []string
+ WebsiteCount QuotaStat
+}
+
+func NewWebsiteController(user *LoggedUser) (*WebsiteController, error) {
+ idx := map[string]*WebsiteId{}
+ var wlist []string
+
+ keyInfo, err := user.S3KeyInfo()
+ if err != nil {
+ return nil, err
+ }
+
+ for _, bckt := range(keyInfo.Buckets) {
+ if len(bckt.GlobalAliases) > 0 {
+ wid := NewWebsiteId(*bckt.Id, bckt.GlobalAliases)
+ idx[wid.Pretty] = wid
+ wlist = append(wlist, wid.Pretty)
+ }
+ }
+ sort.Strings(wlist)
+
+ maxW := user.Quota.WebsiteCount
+ quota := NewQuotaStat(int64(len(wlist)), maxW, true)
+
+ return &WebsiteController { user, idx, wlist, quota }, nil
+}
+
+func (w *WebsiteController) List() []*WebsiteId {
+ r := make([]*WebsiteId, 0, len(w.PrettyList))
+ for _, k := range w.PrettyList {
+ r = append(r, w.WebsiteIdx[k])
+ }
+ return r
+}
+
+func (w *WebsiteController) Inspect(pretty string) (*WebsiteView, error) {
+ website, ok := w.WebsiteIdx[pretty]
+ if !ok {
+ return nil, ErrWebsiteNotFound
+ }
+
+ binfo, err := grgGetBucket(website.Internal)
+ if err != nil {
+ return nil, ErrFetchBucketInfo
+ }
+
+ return NewWebsiteView(binfo), nil
+}
+
+func (w *WebsiteController) Patch(patch *WebsitePatch) (*WebsiteView, error) {
+ return nil, nil
+}
+
+func (w *WebsiteController) Create(pretty string) (*WebsiteView, error) {
+ if pretty == "" {
+ return nil, ErrEmptyBucketName
+ }
+
+ if w.WebsiteCount.IsFull() {
+ return nil, ErrWebsiteQuotaReached
+ }
+
+ binfo, err := grgCreateBucket(pretty)
+ if err != nil {
+ return nil, ErrCantCreateBucket
+ }
+
+ s3key, err := w.User.S3KeyInfo()
+ if err != nil {
+ return nil, err
+ }
+
+ binfo, err = grgAllowKeyOnBucket(*binfo.Id, *s3key.AccessKeyId)
+ if err != nil {
+ return nil, ErrCantAllowKey
+ }
+
+ qr := w.User.Quota.DefaultWebsiteQuota()
+ wr := allowWebsiteDefault()
+
+ ur := garage.NewUpdateBucketRequest()
+ ur.SetWebsiteAccess(*wr)
+ ur.SetQuotas(*qr)
+
+
+ binfo, err = grgUpdateBucket(*binfo.Id, ur)
+ if err != nil {
+ return nil, ErrCantConfigureBucket
+ }
+
+ return NewWebsiteView(binfo), nil
+}
+
+
+type WebsiteView struct {
+ Name *WebsiteId
+ Size QuotaStat
+ Files QuotaStat
+}
+
+func NewWebsiteView(binfo *garage.BucketInfo) *WebsiteView {
+ q := binfo.GetQuotas()
+
+ wid := NewWebsiteIdFromBucketInfo(binfo)
+ size := NewQuotaStat(*binfo.Bytes, (&q).GetMaxSize(), true)
+ objects := NewQuotaStat(*binfo.Objects, (&q).GetMaxObjects(), false)
+ return &WebsiteView { wid, size, objects }
+}
+
+type WebsitePatch struct {
+ size int64
+}