From 411f915fdde659752e6f6e805c7ac2587a922635 Mon Sep 17 00:00:00 2001
From: Tamal Saha
Date: Sun, 17 Mar 2024 09:13:52 -0700
Subject: [PATCH] Add coupon code support
Signed-off-by: Tamal Saha
---
README.md | 4 ++--
main_extras.go | 2 +-
pkg/server/coupon.go | 34 ++++++++++++++++++++++++++++++++++
pkg/server/enterprise.go | 2 +-
pkg/server/options.go | 5 +++++
pkg/server/server.go | 37 +++++++++++++++++++++++++++++++------
pkg/server/types.go | 1 +
templates/index.html | 6 ++++++
8 files changed, 81 insertions(+), 10 deletions(-)
create mode 100644 pkg/server/coupon.go
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 @@ AppsCode License Server
>
+
+
+
+
+
+