diff --git a/README.md b/README.md index d569db6f..2f50173f 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ These instructions are useful if you are trying to deploy your own license serve - Download pre-built binary into a server ```bash -curl -fsSL -O https://github.com/bytebuilders/offline-license-server/releases/download/v0.0.59/offline-license-server-linux-amd64 +curl -fsSL -O https://github.com/bytebuilders/offline-license-server/releases/download/v0.0.61/offline-license-server-linux-amd64 chmod +x offline-license-server-linux-amd64 mv offline-license-server-linux-amd64 /usr/local/bin/offline-license-server sudo systemctl restart offline-license-server @@ -86,7 +86,7 @@ sudo systemctl restart offline-license-server - Install systemd service ```bash -curl -fsSL -O https://github.com/bytebuilders/offline-license-server/raw/v0.0.59/hack/systemd/offline-license-server.service +curl -fsSL -O https://github.com/bytebuilders/offline-license-server/raw/v0.0.61/hack/systemd/offline-license-server.service chmod +x offline-license-server.service # 1. Copy Google cloud service account json key to /root/app/gcloud.json diff --git a/main_extras.go b/main_extras.go index 0f119b11..5fd7c9f2 100644 --- a/main_extras.go +++ b/main_extras.go @@ -88,7 +88,7 @@ func main_sheets() { Timestamp: time.Now().UTC().Format(time.RFC3339), } - err = server.LogLicense(si, &info) + err = server.LogLicense(si, &info, "") if err != nil { klog.Fatal(err) } diff --git a/pkg/server/coupon.go b/pkg/server/coupon.go new file mode 100644 index 00000000..f694d606 --- /dev/null +++ b/pkg/server/coupon.go @@ -0,0 +1,34 @@ +/* +Copyright AppsCode Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package server + +import "strings" + +func ParseCouponCodes(in string) map[string]string { + parts := strings.FieldsFunc(in, func(r rune) bool { + return r == ',' || r == ';' + }) + + couponCodes := map[string]string{} + for _, part := range parts { + if event, code, ok := strings.Cut(part, "="); ok { + couponCodes[code] = event + } + } + + return couponCodes +} diff --git a/pkg/server/enterprise.go b/pkg/server/enterprise.go index e3f8c153..0d7cb276 100644 --- a/pkg/server/enterprise.go +++ b/pkg/server/enterprise.go @@ -29,7 +29,7 @@ func (s *Server) IssueEnterpriseLicense(info LicenseForm, extendBy time.Duration } { - err = LogLicense(s.sheet, accesslog) + err = LogLicense(s.sheet, accesslog, "") if err != nil { return err } diff --git a/pkg/server/options.go b/pkg/server/options.go index d598068d..b7167031 100644 --- a/pkg/server/options.go +++ b/pkg/server/options.go @@ -53,6 +53,8 @@ type Options struct { BlockedEmails []string EnableDripCampaign bool + + Coupons string } func NewOptions() *Options { @@ -75,6 +77,7 @@ func NewOptions() *Options { listmonkPassword: os.Getenv("LISTMONK_PASSWORD"), GoogleCredentialDir: cwd, EnableDripCampaign: true, + Coupons: os.Getenv("COUPONS"), } } @@ -108,4 +111,6 @@ func (s *Options) AddFlags(fs *pflag.FlagSet) { fs.StringSliceVar(&s.BlockedEmails, "blocked-emails", s.BlockedEmails, "Emails blocked from downloading license automatically") fs.BoolVar(&s.EnableDripCampaign, "drip-campaign", s.EnableDripCampaign, "Set true to enable drip campaign runner") + + fs.StringVar(&s.Coupons, "coupons", s.Coupons, "Coupon codes") } diff --git a/pkg/server/server.go b/pkg/server/server.go index 9bfe605a..1e7e7b15 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -85,6 +85,8 @@ type Server struct { blockedDomains sets.String blockedEmails sets.String + + couponCodes map[string]string } func New(opts *Options) (*Server, error) { @@ -171,6 +173,7 @@ func New(opts *Options) (*Server, error) { zoomAccountEmail: os.Getenv("ZOOM_ACCOUNT_EMAIL"), blockedDomains: sets.NewString(opts.BlockedDomains...), blockedEmails: sets.NewString(opts.BlockedEmails...), + couponCodes: ParseCouponCodes(opts.Coupons), }, nil } @@ -432,7 +435,7 @@ func (s *Server) HandleIssueLicense(ctx *macaron.Context, info LicenseForm) erro if err != nil { return err } - err = s.recordLicenseEvent(ctx, info, timestamp, EventTypeLicenseBlocked) + err = s.recordLicenseEvent(ctx, info, timestamp, "", EventTypeLicenseBlocked) if err != nil { return err } @@ -456,6 +459,11 @@ func (s *Server) HandleIssueLicense(ctx *macaron.Context, info LicenseForm) erro if err != nil { return err } + couponEvent, couponOK := s.couponCodes[info.Coupon] + if couponOK { + oneyr := metav1.Duration{Duration: DefaultTTLForCommunityProduct} + license.TTL = &oneyr + } crtLicense, err := s.CreateOrRetrieveLicense(info, *license, info.Cluster) if err != nil { return err @@ -525,7 +533,7 @@ func (s *Server) HandleIssueLicense(ctx *macaron.Context, info LicenseForm) erro // return err //} - err = s.recordLicenseEvent(ctx, info, timestamp, EventTypeLicenseIssued) + err = s.recordLicenseEvent(ctx, info, timestamp, couponEvent, EventTypeLicenseIssued) return }() } @@ -565,7 +573,7 @@ func (s *Server) HandleIssueLicense(ctx *macaron.Context, info LicenseForm) erro return nil } -func (s *Server) recordLicenseEvent(ctx *macaron.Context, info LicenseForm, timestamp string, event LicenseEventType) error { +func (s *Server) recordLicenseEvent(ctx *macaron.Context, info LicenseForm, timestamp, couponEvent string, event LicenseEventType) error { domain := Domain(info.Email) // record request @@ -594,7 +602,7 @@ func (s *Server) recordLicenseEvent(ctx *macaron.Context, info LicenseForm, time return err } - err = LogLicense(s.sheet, &accesslog) + err = LogLicense(s.sheet, &accesslog, couponEvent) if err != nil { return err } @@ -679,12 +687,29 @@ func (s *Server) CreateOrRetrieveLicense(info LicenseForm, license ProductLicens return CreateLicense(s.fs, s.certs, info, license, cluster, nil) } -func LogLicense(si *gdrive.Spreadsheet, info *LogEntry) error { +func LogLicense(si *gdrive.Spreadsheet, info *LogEntry, couponEvent string) error { const sheetName = "License Issue Log" sheetId, err := si.EnsureSheet(sheetName, LogEntry{}.Headers()) if err != nil { return err } - return si.AppendRowData(sheetId, info.Data(), false) + err = si.AppendRowData(sheetId, info.Data(), false) + if err != nil { + return err + } + + if couponEvent != "" { + couponSheet := "COUPON_" + couponEvent + couponSheetId, err := si.EnsureSheet(couponSheet, LogEntry{}.Headers()) + if err != nil { + return err + } + err = si.AppendRowData(couponSheetId, info.Data(), false) + if err != nil { + return err + } + } + + return nil } diff --git a/pkg/server/types.go b/pkg/server/types.go index ce96dd99..9e38ca97 100644 --- a/pkg/server/types.go +++ b/pkg/server/types.go @@ -50,6 +50,7 @@ type LicenseForm struct { Cluster string `form:"cluster" binding:"Required" json:"cluster"` Tos string `form:"tos" binding:"Required" json:"tos"` Token string `form:"token" json:"token"` + Coupon string `form:"coupon" json:"coupon"` } type LicenseMailData struct { diff --git a/templates/index.html b/templates/index.html index 8350c721..c496d8f8 100644 --- a/templates/index.html +++ b/templates/index.html @@ -91,6 +91,12 @@