Skip to content

Commit

Permalink
Merge pull request #328 from zgoat/gh
Browse files Browse the repository at this point in the history
Track billing amount, add form to set GitHub sponsors
  • Loading branch information
arp242 committed Jul 3, 2020
2 parents 3ca1f43 + cb56814 commit 3c61ac5
Show file tree
Hide file tree
Showing 13 changed files with 485 additions and 321 deletions.
23 changes: 13 additions & 10 deletions admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ import (
)

type AdminStat struct {
ID int64 `db:"id"`
Parent *int64 `db:"parent"`
Code string `db:"code"`
Stripe *string `db:"stripe"`
LinkDomain string `db:"link_domain"`
CreatedAt time.Time `db:"created_at"`
Plan string `db:"plan"`
LastMonth int `db:"last_month"`
Total int `db:"total"`
ID int64 `db:"id"`
Parent *int64 `db:"parent"`
Code string `db:"code"`
Stripe *string `db:"stripe"`
BillingAmount *string `db:"billing_amount"`
LinkDomain string `db:"link_domain"`
Email string `db:"email"`
CreatedAt time.Time `db:"created_at"`
Plan string `db:"plan"`
LastMonth int `db:"last_month"`
Total int `db:"total"`
}

type AdminStats []AdminStat
Expand All @@ -45,13 +47,15 @@ func (a *AdminStats) List(ctx context.Context) error {
sites.parent,
sites.code,
sites.created_at,
sites.billing_amount,
(case
when sites.stripe is null then 'free'
when substr(sites.stripe, 0, 9) = 'cus_free' then 'free'
else sites.plan
end) as plan,
stripe,
sites.link_domain,
(select email from users where site=sites.id or site=sites.parent) as email,
coalesce((
select sum(hit_counts.total) from hit_counts where site=sites.id
), 0) as total,
Expand All @@ -60,7 +64,6 @@ func (a *AdminStats) List(ctx context.Context) error {
where site=sites.id and hit_counts.hour >= %s
), 0) as last_month
from sites
group by sites.id, sites.code, sites.created_at, plan
order by last_month desc`, interval(30)))
if err != nil {
return errors.Wrap(err, "AdminStats.List")
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/pgsql/2020-07-03-1-plan-amount.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
begin;
alter table sites add column billing_amount varchar;

insert into version values('2020-07-03-1-plan-amount');
commit;
5 changes: 5 additions & 0 deletions db/migrate/sqlite/2020-07-03-1-plan-amount.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
begin;
alter table sites add column billing_amount varchar;

insert into version values('2020-07-03-1-plan-amount');
commit;
77 changes: 65 additions & 12 deletions handlers/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ func (h admin) mount(r chi.Router) {
//a := r.With(zhttp.Log(true, ""), keyAuth, adminOnly)
a := r.With(zhttp.Log(true, ""), adminOnly)

a.Get("/admin", zhttp.Wrap(h.admin))
a.Get("/admin/sql", zhttp.Wrap(h.adminSQL))
a.Get("/admin/botlog", zhttp.Wrap(h.adminBotlog))
a.Get("/admin/{id}", zhttp.Wrap(h.adminSite))
a.Get("/admin", zhttp.Wrap(h.index))
a.Get("/admin/sql", zhttp.Wrap(h.sql))
a.Get("/admin/botlog", zhttp.Wrap(h.botlog))
a.Get("/admin/{id}", zhttp.Wrap(h.site))
a.Post("/admin/{id}/gh-sponsor", zhttp.Wrap(h.ghSponsor))

//aa.Get("/debug/pprof/*", pprof.Index)
a.Get("/debug/*", func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -47,7 +48,7 @@ func (h admin) mount(r chi.Router) {
a.Get("/debug/pprof/trace", pprof.Trace)
}

func (h admin) admin(w http.ResponseWriter, r *http.Request) error {
func (h admin) index(w http.ResponseWriter, r *http.Request) error {
if goatcounter.MustGetSite(r.Context()).ID != 1 {
return guru.New(403, "yeah nah")
}
Expand Down Expand Up @@ -97,15 +98,15 @@ func (h admin) admin(w http.ResponseWriter, r *http.Request) error {
l = l.Since("signups")

l.FieldsSince().Debug("admin")
return zhttp.Template(w, "backend_admin.gohtml", struct {
return zhttp.Template(w, "admin.gohtml", struct {
Globals
Stats goatcounter.AdminStats
Signups []goatcounter.Stat
MaxSignups int
}{newGlobals(w, r), a, signups, maxSignups})
}

func (h admin) adminSQL(w http.ResponseWriter, r *http.Request) error {
func (h admin) sql(w http.ResponseWriter, r *http.Request) error {
if goatcounter.MustGetSite(r.Context()).ID != 1 {
return guru.New(403, "yeah nah")
}
Expand Down Expand Up @@ -157,7 +158,7 @@ func (h admin) adminSQL(w http.ResponseWriter, r *http.Request) error {
return err
}

return zhttp.Template(w, "backend_admin_sql.gohtml", struct {
return zhttp.Template(w, "admin_sql.gohtml", struct {
Globals
Filter string
Order string
Expand All @@ -173,7 +174,7 @@ func (h admin) adminSQL(w http.ResponseWriter, r *http.Request) error {
idx, prog})
}

func (h admin) adminBotlog(w http.ResponseWriter, r *http.Request) error {
func (h admin) botlog(w http.ResponseWriter, r *http.Request) error {
if goatcounter.MustGetSite(r.Context()).ID != 1 {
return guru.New(403, "yeah nah")
}
Expand All @@ -184,13 +185,13 @@ func (h admin) adminBotlog(w http.ResponseWriter, r *http.Request) error {
return err
}

return zhttp.Template(w, "backend_admin_botlog.gohtml", struct {
return zhttp.Template(w, "admin_botlog.gohtml", struct {
Globals
BotlogIP goatcounter.AdminBotlogIPs
}{newGlobals(w, r), ips})
}

func (h admin) adminSite(w http.ResponseWriter, r *http.Request) error {
func (h admin) site(w http.ResponseWriter, r *http.Request) error {
if goatcounter.MustGetSite(r.Context()).ID != 1 {
return guru.New(403, "yeah nah")
}
Expand All @@ -216,8 +217,60 @@ func (h admin) adminSite(w http.ResponseWriter, r *http.Request) error {
return err
}

return zhttp.Template(w, "backend_admin_site.gohtml", struct {
return zhttp.Template(w, "admin_site.gohtml", struct {
Globals
Stat goatcounter.AdminSiteStat
}{newGlobals(w, r), a})
}

func (h admin) ghSponsor(w http.ResponseWriter, r *http.Request) error {
if goatcounter.MustGetSite(r.Context()).ID != 1 {
return guru.New(403, "yeah nah")
}

v := zvalidate.New()
id := v.Integer("id", chi.URLParam(r, "id"))

var args struct {
User string `json:"user"`
Amount string `json:"amount"`
Plan string `json:"plan"`
}
_, err := zhttp.Decode(r, &args)
if err != nil {
zhttp.FlashError(w, err.Error())
return zhttp.SeeOther(w, fmt.Sprintf("/admin/%d", id))
}

v.Required("plan", args.Plan)
v.Include("plan", args.Plan, goatcounter.Plans)
if v.HasErrors() {
zhttp.FlashError(w, v.Error())
return zhttp.SeeOther(w, fmt.Sprintf("/admin/%d", id))
}

var site goatcounter.Site
err = site.ByID(r.Context(), id)
if err != nil {
zhttp.FlashError(w, err.Error())
return zhttp.SeeOther(w, fmt.Sprintf("/admin/%d", id))
}

if args.User != "" && !strings.HasPrefix(args.Amount, "USD ") {
args.Amount = "USD " + args.Amount
}
if args.User == "" {
args.User = fmt.Sprintf("cus_free_%d", site.ID)
} else if !strings.HasPrefix(args.User, "cus_github_") {
args.User = "cus_github_" + args.User
}

ctx := goatcounter.WithSite(goatcounter.NewContext(r.Context()), &site)
err = site.UpdateStripe(ctx, args.User, args.Plan, args.Amount)
if err != nil {
zhttp.FlashError(w, err.Error())
return zhttp.SeeOther(w, fmt.Sprintf("/admin/%d", id))
}

return zhttp.SeeOther(w, fmt.Sprintf("/admin/%d", id))
}
15 changes: 11 additions & 4 deletions handlers/billing.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ func (h billing) start(w http.ResponseWriter, r *http.Request) error {
if args.Plan == goatcounter.PlanPersonal && quantity == 0 {
err := site.UpdateStripe(r.Context(),
fmt.Sprintf("cus_free_%d", site.ID),
goatcounter.PlanPersonal)
goatcounter.PlanPersonal, "")
if err != nil {
return err
}
Expand Down Expand Up @@ -233,7 +233,7 @@ func (h billing) cancel(w http.ResponseWriter, r *http.Request) error {
}

err := zdb.TX(r.Context(), func(ctx context.Context, db zdb.DB) error {
err := site.UpdateStripe(r.Context(), *site.Stripe, goatcounter.PlanPersonal)
err := site.UpdateStripe(r.Context(), *site.Stripe, goatcounter.PlanPersonal, "")
if err != nil {
return err
}
Expand Down Expand Up @@ -278,7 +278,10 @@ type Session struct {
ClientReferenceID string `json:"client_reference_id"`
Customer string `json:"customer"`
DisplayItems []struct {
Plan struct {
Amount int `json:"amount"`
Currency string `json:"currency"`
Quantity int `json:"quantity"`
Plan struct {
Nickname string `json:"nickname"`
} `json:"plan"`
} `json:"display_items"`
Expand All @@ -301,6 +304,8 @@ func (h billing) stripeWebhook(w http.ResponseWriter, r *http.Request) error {
return err
}

fmt.Println(string(event.Data.Raw))

if strings.HasPrefix(s.ClientReferenceID, "one-time") {
bgrun.Run(func() {
t := "New one-time donation: " + s.ClientReferenceID
Expand Down Expand Up @@ -328,7 +333,9 @@ func (h billing) stripeWebhook(w http.ResponseWriter, r *http.Request) error {
return
}

err = site.UpdateStripe(ctx, s.Customer, s.DisplayItems[0].Plan.Nickname)
amount := fmt.Sprintf("%s %d", strings.ToUpper(s.DisplayItems[0].Currency),
s.DisplayItems[0].Amount*s.DisplayItems[0].Quantity/100)
err = site.UpdateStripe(ctx, s.Customer, s.DisplayItems[0].Plan.Nickname, amount)
if err != nil {
l.Error(err)
return
Expand Down

0 comments on commit 3c61ac5

Please sign in to comment.