2019-10-10 18:12:23 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package satellitedb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-11-05 13:16:02 +00:00
|
|
|
"database/sql"
|
2020-07-14 14:04:38 +01:00
|
|
|
"errors"
|
2019-11-05 13:16:02 +00:00
|
|
|
"time"
|
2019-10-10 18:12:23 +01:00
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
"github.com/zeebo/errs"
|
|
|
|
|
2020-03-30 10:08:50 +01:00
|
|
|
"storj.io/common/uuid"
|
2023-04-06 12:41:14 +01:00
|
|
|
"storj.io/storj/satellite/payments/stripe"
|
2020-01-15 02:29:51 +00:00
|
|
|
"storj.io/storj/satellite/satellitedb/dbx"
|
2019-10-10 18:12:23 +01:00
|
|
|
)
|
|
|
|
|
2019-11-04 14:37:39 +00:00
|
|
|
// ensures that customers implements stripecoinpayments.CustomersDB.
|
2023-04-06 12:41:14 +01:00
|
|
|
var _ stripe.CustomersDB = (*customers)(nil)
|
2019-11-04 12:30:07 +00:00
|
|
|
|
2019-10-11 16:00:35 +01:00
|
|
|
// customers is an implementation of stripecoinpayments.CustomersDB.
|
2019-11-05 13:16:02 +00:00
|
|
|
//
|
|
|
|
// architecture: Database
|
2019-10-10 18:12:23 +01:00
|
|
|
type customers struct {
|
2019-12-14 02:29:54 +00:00
|
|
|
db *satelliteDB
|
2019-10-10 18:12:23 +01:00
|
|
|
}
|
|
|
|
|
2021-03-04 22:55:48 +00:00
|
|
|
// Raw returns the raw dbx handle.
|
|
|
|
func (customers *customers) Raw() *dbx.DB {
|
|
|
|
return customers.db.DB
|
|
|
|
}
|
|
|
|
|
2019-10-10 18:12:23 +01:00
|
|
|
// Insert inserts a stripe customer into the database.
|
|
|
|
func (customers *customers) Insert(ctx context.Context, userID uuid.UUID, customerID string) (err error) {
|
|
|
|
defer mon.Task()(&ctx, userID, customerID)(&err)
|
|
|
|
|
2019-10-15 19:05:45 +01:00
|
|
|
_, err = customers.db.Create_StripeCustomer(
|
2019-10-10 18:12:23 +01:00
|
|
|
ctx,
|
2019-10-15 19:05:45 +01:00
|
|
|
dbx.StripeCustomer_UserId(userID[:]),
|
|
|
|
dbx.StripeCustomer_CustomerId(customerID),
|
2023-03-22 20:23:44 +00:00
|
|
|
dbx.StripeCustomer_Create_Fields{},
|
2019-10-10 18:12:23 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
2019-10-11 16:00:35 +01:00
|
|
|
|
2019-10-23 18:33:24 +01:00
|
|
|
// GetCustomerID returns stripe customers id.
|
|
|
|
func (customers *customers) GetCustomerID(ctx context.Context, userID uuid.UUID) (_ string, err error) {
|
2019-10-11 16:00:35 +01:00
|
|
|
defer mon.Task()(&ctx, userID)(&err)
|
|
|
|
|
2019-10-15 19:05:45 +01:00
|
|
|
idRow, err := customers.db.Get_StripeCustomer_CustomerId_By_UserId(ctx, dbx.StripeCustomer_UserId(userID[:]))
|
2019-10-11 16:00:35 +01:00
|
|
|
if err != nil {
|
2020-07-14 14:04:38 +01:00
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
2023-04-06 12:41:14 +01:00
|
|
|
return "", stripe.ErrNoCustomer
|
2019-11-05 13:16:02 +00:00
|
|
|
}
|
|
|
|
|
2019-10-11 16:00:35 +01:00
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return idRow.CustomerId, nil
|
|
|
|
}
|
2019-11-05 13:16:02 +00:00
|
|
|
|
2023-02-13 17:32:39 +00:00
|
|
|
// GetUserID return userID given stripe customer id.
|
|
|
|
func (customers *customers) GetUserID(ctx context.Context, customerID string) (_ uuid.UUID, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
idRow, err := customers.db.Get_StripeCustomer_UserId_By_CustomerId(ctx, dbx.StripeCustomer_CustomerId(customerID))
|
|
|
|
if err != nil {
|
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
2023-04-06 12:41:14 +01:00
|
|
|
return uuid.UUID{}, stripe.ErrNoCustomer
|
2023-02-13 17:32:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return uuid.UUID{}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return uuid.FromBytes(idRow.UserId)
|
|
|
|
}
|
|
|
|
|
2019-11-05 13:16:02 +00:00
|
|
|
// List returns paginated customers id list, with customers created before specified date.
|
2023-04-06 11:22:36 +01:00
|
|
|
func (customers *customers) List(ctx context.Context, userIDCursor uuid.UUID, limit int, before time.Time) (page stripe.CustomersPage, err error) {
|
2019-11-05 13:16:02 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
rows, err := customers.db.QueryContext(ctx, customers.db.Rebind(`
|
|
|
|
SELECT
|
2023-04-19 20:48:36 +01:00
|
|
|
stripe_customers.user_id, stripe_customers.customer_id, stripe_customers.package_plan, stripe_customers.purchased_package_at
|
2023-04-06 11:22:36 +01:00
|
|
|
FROM
|
|
|
|
stripe_customers
|
|
|
|
WHERE
|
|
|
|
stripe_customers.user_id > ? AND
|
|
|
|
stripe_customers.created_at < ?
|
|
|
|
ORDER BY stripe_customers.user_id ASC
|
|
|
|
LIMIT ?
|
|
|
|
`), userIDCursor, before, limit+1)
|
2019-11-05 13:16:02 +00:00
|
|
|
if err != nil {
|
2023-04-06 11:22:36 +01:00
|
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
|
|
return stripe.CustomersPage{}, nil
|
|
|
|
}
|
2023-04-06 12:41:14 +01:00
|
|
|
return stripe.CustomersPage{}, err
|
2019-11-05 13:16:02 +00:00
|
|
|
}
|
2023-04-06 11:22:36 +01:00
|
|
|
defer func() { err = errs.Combine(err, rows.Close()) }()
|
2019-11-05 13:16:02 +00:00
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
results := []stripe.Customer{}
|
|
|
|
for rows.Next() {
|
|
|
|
var customer stripe.Customer
|
2023-04-19 20:48:36 +01:00
|
|
|
err := rows.Scan(&customer.UserID, &customer.ID, &customer.PackagePlan, &customer.PackagePurchasedAt)
|
2023-04-06 11:22:36 +01:00
|
|
|
if err != nil {
|
|
|
|
return stripe.CustomersPage{}, errs.New("unable to get stripe customer: %+v", err)
|
|
|
|
}
|
2019-11-05 13:16:02 +00:00
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
results = append(results, customer)
|
|
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
|
|
return stripe.CustomersPage{}, errs.New("error while listing stripe customers: %+v", err)
|
2019-11-05 13:16:02 +00:00
|
|
|
}
|
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
if len(results) == limit+1 {
|
|
|
|
results = results[:len(results)-1]
|
2019-11-05 13:16:02 +00:00
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
page.Next = true
|
|
|
|
page.Cursor = results[len(results)-1].UserID
|
2019-11-05 13:16:02 +00:00
|
|
|
}
|
|
|
|
|
2023-04-06 11:22:36 +01:00
|
|
|
page.Customers = results
|
2019-11-05 13:16:02 +00:00
|
|
|
return page, nil
|
|
|
|
}
|
|
|
|
|
2023-03-22 20:23:44 +00:00
|
|
|
// UpdatePackage updates the customer's package plan and purchase time.
|
2023-04-06 12:41:14 +01:00
|
|
|
func (customers *customers) UpdatePackage(ctx context.Context, userID uuid.UUID, packagePlan *string, timestamp *time.Time) (c *stripe.Customer, err error) {
|
2023-03-22 20:23:44 +00:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
updateFields := dbx.StripeCustomer_Update_Fields{
|
|
|
|
PackagePlan: dbx.StripeCustomer_PackagePlan_Null(),
|
|
|
|
PurchasedPackageAt: dbx.StripeCustomer_PurchasedPackageAt_Null(),
|
|
|
|
}
|
|
|
|
if packagePlan != nil {
|
|
|
|
updateFields.PackagePlan = dbx.StripeCustomer_PackagePlan(*packagePlan)
|
|
|
|
}
|
|
|
|
if timestamp != nil {
|
|
|
|
updateFields.PurchasedPackageAt = dbx.StripeCustomer_PurchasedPackageAt(*timestamp)
|
|
|
|
}
|
|
|
|
|
|
|
|
dbxCustomer, err := customers.db.Update_StripeCustomer_By_UserId(ctx,
|
|
|
|
dbx.StripeCustomer_UserId(userID[:]),
|
|
|
|
updateFields,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
return fromDBXCustomer(dbxCustomer)
|
|
|
|
}
|
|
|
|
|
|
|
|
// UpdatePackage updates the customer's package plan and purchase time.
|
|
|
|
func (customers *customers) GetPackageInfo(ctx context.Context, userID uuid.UUID) (_ *string, _ *time.Time, err error) {
|
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
|
|
|
row, err := customers.db.Get_StripeCustomer_PackagePlan_StripeCustomer_PurchasedPackageAt_By_UserId(ctx, dbx.StripeCustomer_UserId(userID[:]))
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
return row.PackagePlan, row.PurchasedPackageAt, nil
|
|
|
|
}
|
|
|
|
|
2019-11-05 13:16:02 +00:00
|
|
|
// fromDBXCustomer converts *dbx.StripeCustomer to *stripecoinpayments.Customer.
|
2023-04-06 12:41:14 +01:00
|
|
|
func fromDBXCustomer(dbxCustomer *dbx.StripeCustomer) (*stripe.Customer, error) {
|
2020-03-31 17:49:16 +01:00
|
|
|
userID, err := uuid.FromBytes(dbxCustomer.UserId)
|
2019-11-05 13:16:02 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2023-04-06 12:41:14 +01:00
|
|
|
return &stripe.Customer{
|
2023-03-22 20:23:44 +00:00
|
|
|
ID: dbxCustomer.CustomerId,
|
|
|
|
UserID: userID,
|
|
|
|
PackagePlan: dbxCustomer.PackagePlan,
|
|
|
|
PackagePurchasedAt: dbxCustomer.PurchasedPackageAt,
|
2019-11-05 13:16:02 +00:00
|
|
|
}, nil
|
|
|
|
}
|