storj/satellite/console/usercredits_test.go

343 lines
10 KiB
Go
Raw Normal View History

// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
package console_test
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
"storj.io/common/testcontext"
"storj.io/common/testrand"
"storj.io/storj/private/currency"
"storj.io/storj/satellite"
"storj.io/storj/satellite/console"
"storj.io/storj/satellite/rewards"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
)
func TestUserCredits(t *testing.T) {
t.Skip("Skip until usercredits.Create method is cockroach compatible. https://github.com/cockroachdb/cockroach/issues/42881")
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
consoleDB := db.Console()
user, referrer, activeOffer, defaultOffer := setupData(ctx, t, db)
randomID := testrand.UUID()
invalidOffer := rewards.Offer{
ID: 10,
}
// test foreign key constraint for inserting a new user credit entry with randomID
var invalidUserCredits []console.CreateCredit
invalid1, err := console.NewCredit(activeOffer, console.Invitee, randomID, &referrer.ID)
require.NoError(t, err)
invalid2, err := console.NewCredit(&invalidOffer, console.Invitee, user.ID, &referrer.ID)
require.NoError(t, err)
invalid3, err := console.NewCredit(activeOffer, console.Invitee, randomID, &randomID)
require.NoError(t, err)
invalidUserCredits = append(invalidUserCredits, *invalid1, *invalid2, *invalid3)
for _, ivc := range invalidUserCredits {
err := consoleDB.UserCredits().Create(ctx, ivc)
require.Error(t, err)
}
type result struct {
remainingCharge int
usage console.UserCreditUsage
referred int64
hasUpdateErr bool
hasCreateErr bool
}
var validUserCredits = []struct {
userCredit console.CreateCredit
chargedCredits int
expected result
}{
{
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: activeOffer.RedeemableCap,
Status: activeOffer.Status,
Type: activeOffer.Type,
},
UserID: user.ID,
OfferID: activeOffer.ID,
ReferredBy: &referrer.ID,
Type: console.Invitee,
CreditsEarned: currency.Cents(100),
ExpiresAt: time.Now().UTC().AddDate(0, 1, 0),
},
chargedCredits: 120,
expected: result{
remainingCharge: 20,
usage: console.UserCreditUsage{
AvailableCredits: currency.Cents(0),
UsedCredits: currency.Cents(100),
Referred: 0,
},
referred: 0,
},
},
{
// simulate a credit that's already expired
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: activeOffer.RedeemableCap,
Status: activeOffer.Status,
Type: activeOffer.Type,
},
UserID: user.ID,
OfferID: activeOffer.ID,
ReferredBy: &referrer.ID,
Type: console.Invitee,
CreditsEarned: currency.Cents(100),
ExpiresAt: time.Now().UTC().AddDate(0, 0, -5),
},
chargedCredits: 60,
expected: result{
remainingCharge: 60,
usage: console.UserCreditUsage{
AvailableCredits: currency.Cents(0),
UsedCredits: currency.Cents(100),
Referred: 0,
},
referred: 0,
hasCreateErr: true,
hasUpdateErr: true,
},
},
{
// simulate a credit that's not expired
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: activeOffer.RedeemableCap,
Status: activeOffer.Status,
Type: activeOffer.Type,
},
UserID: user.ID,
OfferID: activeOffer.ID,
ReferredBy: &referrer.ID,
Type: console.Invitee,
CreditsEarned: currency.Cents(100),
ExpiresAt: time.Now().UTC().AddDate(0, 0, 5),
},
chargedCredits: 80,
expected: result{
remainingCharge: 0,
usage: console.UserCreditUsage{
AvailableCredits: currency.Cents(20),
UsedCredits: currency.Cents(180),
Referred: 0,
},
referred: 0,
},
},
{
// simulate redeemable capacity has been reached for active offers
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: 1,
Status: activeOffer.Status,
Type: activeOffer.Type,
},
UserID: user.ID,
OfferID: activeOffer.ID,
ReferredBy: &randomID,
Type: console.Invitee,
CreditsEarned: currency.Cents(100),
ExpiresAt: time.Now().UTC().AddDate(0, 1, 0),
},
expected: result{
usage: console.UserCreditUsage{
Referred: 0,
AvailableCredits: currency.Cents(20),
UsedCredits: currency.Cents(180),
},
referred: 0,
hasCreateErr: true,
},
},
{
// simulate redeemable capacity has been reached for default offers
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: defaultOffer.RedeemableCap,
Status: defaultOffer.Status,
Type: defaultOffer.Type,
},
UserID: user.ID,
OfferID: defaultOffer.ID,
ReferredBy: nil,
Type: console.Invitee,
CreditsEarned: currency.Cents(100),
ExpiresAt: time.Now().UTC().AddDate(0, 1, 0),
},
expected: result{
usage: console.UserCreditUsage{
Referred: 0,
AvailableCredits: currency.Cents(120),
UsedCredits: currency.Cents(180),
},
referred: 0,
hasCreateErr: false,
},
},
satellite/satellitedb: add updateEarnedCredits method for user_credits table (#2609) * parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581673 -0400 parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581428 -0400 satellite/console: add referral link logic (#2576) * setup referral route * referredBy * add user id * modify user query * separate optional field from userInfo * get current reward on init of satellite gui * remove unsed code * fix format * only apply 0 credit on registration * only pass required information for rewards * fix time parsing * fix test and linter * rename method * add todo * remove user referral logic * add null check and fix format * get current offer * remove partnerID on CreateUser struct * fix storj-sim user creation * only redeem credit when there's an offer * fix default offer configuration * fix migration * Add helper function for get correct credit duration * add comment * only store userid into user_credit table * add check for partner id to set correct offer type * change free credit to use invitee credits * remove unecessary code * add credit update in activateAccount * remove unused code * fix format * close reader and fix front-end build * move create credit logic into CreateUser method * when there's no offer set, user flow shouldn't be interrupted by referral program * add appropriate error messages * remove unused code * add comment * add error class for no current offer error * add error class for credits update * add comment for migration * only log secret when it's in debug level * fix typo * add testdata
2019-07-30 14:21:00 +01:00
{
// simulate credit on account creation
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: defaultOffer.RedeemableCap,
Status: defaultOffer.Status,
Type: defaultOffer.Type,
},
satellite/satellitedb: add updateEarnedCredits method for user_credits table (#2609) * parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581673 -0400 parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581428 -0400 satellite/console: add referral link logic (#2576) * setup referral route * referredBy * add user id * modify user query * separate optional field from userInfo * get current reward on init of satellite gui * remove unsed code * fix format * only apply 0 credit on registration * only pass required information for rewards * fix time parsing * fix test and linter * rename method * add todo * remove user referral logic * add null check and fix format * get current offer * remove partnerID on CreateUser struct * fix storj-sim user creation * only redeem credit when there's an offer * fix default offer configuration * fix migration * Add helper function for get correct credit duration * add comment * only store userid into user_credit table * add check for partner id to set correct offer type * change free credit to use invitee credits * remove unecessary code * add credit update in activateAccount * remove unused code * fix format * close reader and fix front-end build * move create credit logic into CreateUser method * when there's no offer set, user flow shouldn't be interrupted by referral program * add appropriate error messages * remove unused code * add comment * add error class for no current offer error * add error class for credits update * add comment for migration * only log secret when it's in debug level * fix typo * add testdata
2019-07-30 14:21:00 +01:00
UserID: user.ID,
OfferID: defaultOffer.ID,
ReferredBy: &referrer.ID,
Type: console.Invitee,
satellite/satellitedb: add updateEarnedCredits method for user_credits table (#2609) * parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581673 -0400 parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581428 -0400 satellite/console: add referral link logic (#2576) * setup referral route * referredBy * add user id * modify user query * separate optional field from userInfo * get current reward on init of satellite gui * remove unsed code * fix format * only apply 0 credit on registration * only pass required information for rewards * fix time parsing * fix test and linter * rename method * add todo * remove user referral logic * add null check and fix format * get current offer * remove partnerID on CreateUser struct * fix storj-sim user creation * only redeem credit when there's an offer * fix default offer configuration * fix migration * Add helper function for get correct credit duration * add comment * only store userid into user_credit table * add check for partner id to set correct offer type * change free credit to use invitee credits * remove unecessary code * add credit update in activateAccount * remove unused code * fix format * close reader and fix front-end build * move create credit logic into CreateUser method * when there's no offer set, user flow shouldn't be interrupted by referral program * add appropriate error messages * remove unused code * add comment * add error class for no current offer error * add error class for credits update * add comment for migration * only log secret when it's in debug level * fix typo * add testdata
2019-07-30 14:21:00 +01:00
CreditsEarned: currency.Cents(0),
ExpiresAt: time.Now().UTC().AddDate(0, 1, 0),
},
expected: result{
usage: console.UserCreditUsage{
Referred: 0,
AvailableCredits: currency.Cents(220),
UsedCredits: currency.Cents(180),
},
referred: 0,
hasCreateErr: false,
},
},
{
// simulate credit redemption for referrer
userCredit: console.CreateCredit{
OfferInfo: rewards.RedeemOffer{
RedeemableCap: activeOffer.RedeemableCap,
Status: activeOffer.Status,
Type: activeOffer.Type,
},
UserID: referrer.ID,
OfferID: activeOffer.ID,
ReferredBy: nil,
Type: console.Referrer,
CreditsEarned: activeOffer.AwardCredit,
ExpiresAt: time.Now().UTC().AddDate(0, 0, activeOffer.AwardCreditDurationDays),
},
expected: result{
usage: console.UserCreditUsage{
Referred: 1,
AvailableCredits: activeOffer.AwardCredit,
UsedCredits: currency.Cents(0),
},
referred: 1,
satellite/satellitedb: add updateEarnedCredits method for user_credits table (#2609) * parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581673 -0400 parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581428 -0400 satellite/console: add referral link logic (#2576) * setup referral route * referredBy * add user id * modify user query * separate optional field from userInfo * get current reward on init of satellite gui * remove unsed code * fix format * only apply 0 credit on registration * only pass required information for rewards * fix time parsing * fix test and linter * rename method * add todo * remove user referral logic * add null check and fix format * get current offer * remove partnerID on CreateUser struct * fix storj-sim user creation * only redeem credit when there's an offer * fix default offer configuration * fix migration * Add helper function for get correct credit duration * add comment * only store userid into user_credit table * add check for partner id to set correct offer type * change free credit to use invitee credits * remove unecessary code * add credit update in activateAccount * remove unused code * fix format * close reader and fix front-end build * move create credit logic into CreateUser method * when there's no offer set, user flow shouldn't be interrupted by referral program * add appropriate error messages * remove unused code * add comment * add error class for no current offer error * add error class for credits update * add comment for migration * only log secret when it's in debug level * fix typo * add testdata
2019-07-30 14:21:00 +01:00
hasCreateErr: false,
},
},
}
for _, vc := range validUserCredits {
err := consoleDB.UserCredits().Create(ctx, vc.userCredit)
if vc.expected.hasCreateErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
satellite/satellitedb: add updateEarnedCredits method for user_credits table (#2609) * parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581673 -0400 parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581428 -0400 satellite/console: add referral link logic (#2576) * setup referral route * referredBy * add user id * modify user query * separate optional field from userInfo * get current reward on init of satellite gui * remove unsed code * fix format * only apply 0 credit on registration * only pass required information for rewards * fix time parsing * fix test and linter * rename method * add todo * remove user referral logic * add null check and fix format * get current offer * remove partnerID on CreateUser struct * fix storj-sim user creation * only redeem credit when there's an offer * fix default offer configuration * fix migration * Add helper function for get correct credit duration * add comment * only store userid into user_credit table * add check for partner id to set correct offer type * change free credit to use invitee credits * remove unecessary code * add credit update in activateAccount * remove unused code * fix format * close reader and fix front-end build * move create credit logic into CreateUser method * when there's no offer set, user flow shouldn't be interrupted by referral program * add appropriate error messages * remove unused code * add comment * add error class for no current offer error * add error class for credits update * add comment for migration * only log secret when it's in debug level * fix typo * add testdata
2019-07-30 14:21:00 +01:00
if vc.userCredit.CreditsEarned.Cents() == 0 {
err = consoleDB.UserCredits().UpdateEarnedCredits(ctx, vc.userCredit.UserID)
require.NoError(t, err)
}
{
remainingCharge, err := consoleDB.UserCredits().UpdateAvailableCredits(ctx, vc.chargedCredits, vc.userCredit.UserID, time.Now().UTC())
if vc.expected.hasUpdateErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}
require.Equal(t, vc.expected.remainingCharge, remainingCharge)
}
{
usage, err := consoleDB.UserCredits().GetCreditUsage(ctx, vc.userCredit.UserID, time.Now().UTC())
require.NoError(t, err)
require.Equal(t, vc.expected.usage, *usage)
}
{
referred, err := consoleDB.UserCredits().GetCreditUsage(ctx, referrer.ID, time.Now().UTC())
require.NoError(t, err)
require.Equal(t, vc.expected.referred, referred.Referred)
}
}
})
}
func setupData(ctx context.Context, t *testing.T, db satellite.DB) (user *console.User, referrer *console.User, activeOffer *rewards.Offer, defaultOffer *rewards.Offer) {
consoleDB := db.Console()
offersDB := db.Rewards()
// create user
userPassHash := testrand.Bytes(8)
referrerPassHash := testrand.Bytes(8)
var err error
// create an user
user, err = consoleDB.Users().Insert(ctx, &console.User{
ID: testrand.UUID(),
FullName: "John Doe",
Email: "john@mail.test",
PasswordHash: userPassHash,
Status: console.Active,
})
require.NoError(t, err)
//create an user as referrer
referrer, err = consoleDB.Users().Insert(ctx, &console.User{
ID: testrand.UUID(),
FullName: "referrer",
Email: "referrer@mail.test",
PasswordHash: referrerPassHash,
Status: console.Active,
})
require.NoError(t, err)
// create an active offer
activeOffer, err = offersDB.Create(ctx, &rewards.NewOffer{
Name: "active",
Description: "active offer",
AwardCredit: currency.Cents(100),
InviteeCredit: currency.Cents(50),
AwardCreditDurationDays: 60,
InviteeCreditDurationDays: 30,
RedeemableCap: 50,
ExpiresAt: time.Now().UTC().Add(time.Hour * 1),
Status: rewards.Active,
Type: rewards.Referral,
})
require.NoError(t, err)
// create a default offer
defaultOffer, err = offersDB.Create(ctx, &rewards.NewOffer{
Name: "default",
Description: "default offer",
satellite/satellitedb: add updateEarnedCredits method for user_credits table (#2609) * parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581673 -0400 parent 13dd501042d0fa6eb0142b6f737704985c17f5bc author Yingrong Zhao <yingrong.zhao@gmail.com> 1563560530 -0400 committer Yingrong Zhao <yingrong.zhao@gmail.com> 1563581428 -0400 satellite/console: add referral link logic (#2576) * setup referral route * referredBy * add user id * modify user query * separate optional field from userInfo * get current reward on init of satellite gui * remove unsed code * fix format * only apply 0 credit on registration * only pass required information for rewards * fix time parsing * fix test and linter * rename method * add todo * remove user referral logic * add null check and fix format * get current offer * remove partnerID on CreateUser struct * fix storj-sim user creation * only redeem credit when there's an offer * fix default offer configuration * fix migration * Add helper function for get correct credit duration * add comment * only store userid into user_credit table * add check for partner id to set correct offer type * change free credit to use invitee credits * remove unecessary code * add credit update in activateAccount * remove unused code * fix format * close reader and fix front-end build * move create credit logic into CreateUser method * when there's no offer set, user flow shouldn't be interrupted by referral program * add appropriate error messages * remove unused code * add comment * add error class for no current offer error * add error class for credits update * add comment for migration * only log secret when it's in debug level * fix typo * add testdata
2019-07-30 14:21:00 +01:00
AwardCredit: currency.Cents(0),
InviteeCredit: currency.Cents(100),
AwardCreditDurationDays: 0,
InviteeCreditDurationDays: 14,
RedeemableCap: 0,
ExpiresAt: time.Now().UTC().Add(time.Hour * 1),
Status: rewards.Default,
Type: rewards.FreeCredit,
})
require.NoError(t, err)
return user, referrer, activeOffer, defaultOffer
}