Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update retry handler used by Pro Client #1238

Merged
merged 29 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c25fff5
move code to create user with backoff to pro client
atavism Nov 22, 2024
e11cc27
move code to create user with backoff to pro client
atavism Nov 22, 2024
aa953c9
move create user code to pro client
atavism Nov 22, 2024
c28bde9
clean-ups
atavism Nov 22, 2024
1b45fb0
Update desktop to use same code to retry creating user
atavism Nov 22, 2024
051dbc4
Update desktop to use same code to retry creating user
atavism Nov 22, 2024
dc5bed5
revert changes
atavism Nov 22, 2024
18b9fcd
Add client session mock
atavism Nov 22, 2024
2f83a2f
clean-ups
atavism Nov 22, 2024
aacff92
clean-ups
atavism Nov 22, 2024
36b5fc4
clean-ups
atavism Nov 22, 2024
77d916e
clean-ups
atavism Nov 22, 2024
a60dcf7
merge latest
atavism Dec 1, 2024
5f07f09
update flashlight and run go mod tidy
atavism Dec 1, 2024
ad01305
update flashlight and run go mod tidy
atavism Dec 1, 2024
b742df5
Remove old tests
atavism Dec 1, 2024
b9dc679
Stop polling if user becomes pro and some other clean-ups
atavism Dec 2, 2024
16f1ad7
Fix user create api on android. (#1246)
jigar-f Dec 3, 2024
624b1db
merge latest
atavism Dec 3, 2024
cca94f6
Merge remote-tracking branch 'origin/main' into atavism/updates-pro-c…
atavism Dec 3, 2024
5e8cb2e
Merge remote-tracking branch 'origin/main' into atavism/updates-pro-c…
atavism Dec 4, 2024
a5e31d0
Add back auth methods for now
atavism Dec 4, 2024
1a97e30
Merge remote-tracking branch 'origin/main' into atavism/updates-pro-c…
atavism Dec 4, 2024
4252f78
move plans and payment methods calls to pro client
atavism Dec 4, 2024
779d9cc
move plans and payment methods calls to pro client
atavism Dec 4, 2024
f6e67b7
Fixed issue on desktop while creating user and other small fixes.
jigar-f Dec 5, 2024
68d579d
remove commented code.
jigar-f Dec 5, 2024
fb0e326
clean-ups
atavism Dec 5, 2024
9ef2d82
Merge remote-tracking branch 'origin/main' into atavism/updates-pro-c…
atavism Dec 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions android/.project
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
</natures>
<filteredResources>
<filter>
<id>1620924294143</id>
<id>1732230225439</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
Expand Down
192 changes: 44 additions & 148 deletions desktop/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ type App struct {
ws ws.UIChannel

cachedUserData sync.Map
plansCache sync.Map

onUserData []func(current *protos.User, new *protos.User)

Expand Down Expand Up @@ -384,7 +383,7 @@ func (app *App) OnStatsChange(fn func(stats.Stats)) {
func (app *App) afterStart(cl *flashlightClient.Client) {
ctx := context.Background()
go app.fetchOrCreateUser(ctx)
go app.GetPaymentMethods(ctx)
go app.proClient.DesktopPaymentMethods(ctx)
go app.fetchDeviceLinkingCode(ctx)

app.OnSettingChange(settings.SNSystemProxy, func(val interface{}) {
Expand Down Expand Up @@ -570,17 +569,18 @@ func (app *App) IsPro() bool {
return isPro
}

func (app *App) fetchOrCreateUser(ctx context.Context) (*protos.User, error) {
settings := app.Settings()
lang := settings.GetLanguage()
func (app *App) fetchOrCreateUser(ctx context.Context) {
ss := app.Settings()
lang := ss.GetLanguage()
if lang == "" {
// set default language
settings.SetLanguage("en_us")
ss.SetLanguage("en_us")
}
if userID := settings.GetUserID(); userID == 0 {
return app.CreateUser(ctx)
if userID := ss.GetUserID(); userID == 0 {
ss.SetUserFirstVisit(true)
app.proClient.RetryCreateUser(ctx, app, 5*time.Minute)
} else {
return app.UserData(ctx)
app.proClient.UpdateUserData(ctx, app)
}
}

Expand All @@ -600,145 +600,6 @@ func (app *App) fetchDeviceLinkingCode(ctx context.Context) (string, error) {
return resp.Code, nil
}

// CreateUser is used when Lantern is run for the first time and creates a new user with the pro server
func (app *App) CreateUser(ctx context.Context) (*protos.User, error) {
log.Debug("New user, calling user create")
settings := app.Settings()
settings.SetUserFirstVisit(true)
resp, err := app.proClient.UserCreate(ctx)
if err != nil {
return nil, errors.New("Could not create new Pro user: %v", err)
}
user := resp.User
log.Debugf("DEBUG: User created: %v", user)
if resp.BaseResponse != nil && resp.BaseResponse.Error != "" {
return nil, errors.New("Could not create new Pro user: %v", err)
}
app.SetUserData(ctx, user.UserId, user)
settings.SetReferralCode(user.Referral)
settings.SetUserIDAndToken(user.UserId, user.Token)
go app.UserData(ctx)
return resp.User, nil
}

// Plans returns the plans available to a user
func (app *App) Plans(ctx context.Context) ([]protos.Plan, error) {
if v, ok := app.plansCache.Load("plans"); ok {
resp := v.([]protos.Plan)
log.Debugf("Returning plans from cache %s", v)
return resp, nil
}
resp, err := app.FetchPaymentMethods(ctx)
if err != nil {
return nil, err
}
return resp.Plans, nil
}

// GetPaymentMethods returns the plans and payment from cache if available
// if not then call FetchPaymentMethods
func (app *App) GetPaymentMethods(ctx context.Context) ([]protos.PaymentMethod, error) {
if v, ok := app.plansCache.Load("paymentMethods"); ok {
resp := v.([]protos.PaymentMethod)
log.Debugf("Returning payment methods from cache %s", v)
return resp, nil
}
resp, err := app.FetchPaymentMethods(ctx)
if err != nil {
return nil, err
}
desktopProviders, ok := resp.Providers["desktop"]
if !ok {
return nil, errors.New("No desktop payment providers found")
}
return desktopProviders, nil
}

// FetchPaymentMethods returns the plans and payment plans available to a user
func (app *App) FetchPaymentMethods(ctx context.Context) (*proclient.PaymentMethodsResponse, error) {
resp, err := app.proClient.PaymentMethodsV4(context.Background())
if err != nil {
return nil, errors.New("Could not get payment methods: %v", err)
}
desktopPaymentMethods, ok := resp.Providers["desktop"]
if !ok {
return nil, errors.New("No desktop payment providers found")
}
for i := range desktopPaymentMethods {
paymentMethod := &desktopPaymentMethods[i]
for j, provider := range paymentMethod.Providers {
if resp.Logo[provider.Name] != nil {
logos := resp.Logo[provider.Name].([]interface{})
for _, logo := range logos {
paymentMethod.Providers[j].LogoUrls = append(paymentMethod.Providers[j].LogoUrls, logo.(string))
}
}
}
}
//clear previous store cache
app.plansCache.Delete("plans")
app.plansCache.Delete("paymentMethods")
log.Debugf("DEBUG: Payment methods plans: %+v", resp.Plans)
log.Debugf("DEBUG: Payment methods providers: %+v", desktopPaymentMethods)
app.plansCache.Store("plans", resp.Plans)
app.plansCache.Store("paymentMethods", desktopPaymentMethods)
app.sendConfigOptions()
return resp, nil
}

// UserData looks up user data that is associated with the given UserConfig
func (app *App) UserData(ctx context.Context) (*protos.User, error) {
log.Debug("Refreshing user data")
resp, err := app.proClient.UserData(context.Background())
if err != nil {
return nil, errors.New("error fetching user data: %v", err)
} else if resp.User == nil {
return nil, errors.New("error fetching user data")
}
userDetail := resp.User
settings := app.Settings()

setProUser := func(isPro bool) {
app.Settings().SetProUser(isPro)
}

currentDevice := app.Settings().GetDeviceID()

// Check if device id is connect to same device if not create new user
// this is for the case when user removed device from other device
deviceFound := false
if userDetail.Devices != nil {
for _, device := range userDetail.Devices {
if device.Id == currentDevice {
deviceFound = true
break
}
}
}

/// Check if user has installed app first time
firstTime := settings.GetUserFirstVisit()
log.Debugf("First time visit %v", firstTime)
if userDetail.UserLevel == "pro" && firstTime {
log.Debugf("User is pro and first time")
setProUser(true)
} else if userDetail.UserLevel == "pro" && !firstTime && deviceFound {
log.Debugf("User is pro and not first time")
setProUser(true)
} else {
log.Debugf("User is not pro")
setProUser(false)
}
settings.SetUserIDAndToken(userDetail.UserId, userDetail.Token)
settings.SetExpiration(userDetail.Expiration)
settings.SetReferralCode(resp.User.Referral)
log.Debugf("User caching successful: %+v", userDetail)
// Save data in userData cache
app.SetUserData(ctx, userDetail.UserId, userDetail)
app.SendUpdateUserDataToUI()
return resp.User, nil
}

func (app *App) devices() protos.Devices {
user, found := app.GetUserData(app.Settings().GetUserID())

Expand Down Expand Up @@ -810,3 +671,38 @@ func (app *App) ProClient() proclient.ProClient {
defer app.mu.RUnlock()
return app.proClient
}

// Client session methods
func (app *App) FetchUserData() error {
go app.proClient.UserData(context.Background())
go app.proClient.FetchPaymentMethodsAndCache(context.Background())
return nil
}

func (app *App) GetDeviceID() (string, error) {
return app.Settings().GetDeviceID(), nil
}

func (app *App) GetUserFirstVisit() (bool, error) {
return app.Settings().GetUserFirstVisit(), nil
}

func (app *App) SetUserIDAndToken(id int64, token string) error {
app.Settings().SetUserIDAndToken(id, token)
return nil
}

func (app *App) SetProUser(pro bool) error {
app.Settings().SetProUser(pro)
return nil
}

func (app *App) SetReferralCode(referral string) error {
app.Settings().SetReferralCode(referral)
return nil
}

func (app *App) SetExpiration(exp int64) error {
app.Settings().SetExpiration(exp)
return nil
}
4 changes: 2 additions & 2 deletions desktop/app/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ func (app *App) sendConfigOptions() {
return authEnabled
}
ctx := context.Background()
plans, _ := app.Plans(ctx)
paymentMethods, _ := app.GetPaymentMethods(ctx)
plans, _ := app.proClient.Plans(ctx)
paymentMethods, _ := app.proClient.DesktopPaymentMethods(ctx)
devices, _ := json.Marshal(app.devices())
log.Debugf("DEBUG: Devices: %s", string(devices))
log.Debugf("Expiration date: %s", app.settings.GetExpirationDate())
Expand Down
51 changes: 6 additions & 45 deletions desktop/app/pro.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ import (
"context"
"encoding/json"
"reflect"
"time"

"github.com/getlantern/errors"
"github.com/getlantern/flashlight/v7/common"
"github.com/getlantern/lantern-client/desktop/ws"
"github.com/getlantern/lantern-client/internalsdk/pro"
"github.com/getlantern/lantern-client/internalsdk/protos"
)

// onProStatusChange allows registering an event handler to learn when the
// user's pro status or "yinbi enabled" status has changed.
// user's pro status changes
func (app *App) onProStatusChange(cb func(isPro bool)) {
app.setOnUserData(func(current *protos.User, new *protos.User) {
if current == nil || isActive(current) != isActive(new) {
Expand Down Expand Up @@ -109,53 +107,16 @@ func (app *App) IsProUserFast(uc common.UserConfig) (isPro bool, statusKnown boo
// It loops forever in 10 seconds interval until the user is fetched or
// created, as it's fundamental for the UI to work.
func (app *App) servePro(channel ws.UIChannel) error {
chFetch := make(chan bool)
ctx := context.Background()
go func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atavism We were creating two users like in android, We don't need this anymore, Since we are creating user in afterStart

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for removing this!

fetchOrCreate := func() error {
userID := app.settings.GetUserID()
if userID == 0 {
resp, err := app.proClient.UserCreate(ctx)
if err != nil {
return errors.New("Could not create new Pro user: %v", err)
}
app.settings.SetUserIDAndToken(resp.User.UserId, resp.User.Token)
} else {
_, err := app.proClient.UserData(ctx)
if err != nil {
return errors.New("Could not get user data for %v: %v", userID, err)
}
}
return nil
}

retry := time.NewTimer(0)
retryOnFail := func(drainChannel bool) {
if err := fetchOrCreate(); err != nil {
if drainChannel && !retry.Stop() {
<-retry.C
}
retry.Reset(10 * time.Second)
}
}
for {
select {
case <-chFetch:
retryOnFail(true)
case <-retry.C:
retryOnFail(false)
}
}
}()

service, err := channel.Register("pro", nil)
if err != nil {
return err
}
app.setOnUserData(func(current *protos.User, new *protos.User) {
b, _ := json.Marshal(new)
log.Debugf("Sending updated user data to all clients: %s", string(b))
service.Out <- new
if new != nil {
b, _ := json.Marshal(new)
log.Debugf("Sending updated user data to all clients: %s", string(b))
service.Out <- new
}
})
return err
}
11 changes: 5 additions & 6 deletions desktop/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func signup(email *C.char, password *C.char) *C.char {
saveUserSalt(salt)
setting.SetEmailAddress(C.GoString(email))
a.SetUserLoggedIn(true)
a.FetchPaymentMethods(context.Background())
a.ProClient().FetchPaymentMethodsAndCache(context.Background())
return C.CString("true")
}

Expand Down Expand Up @@ -129,7 +129,7 @@ func logout() *C.char {

clearLocalUserData()
// Create new user
atavism marked this conversation as resolved.
Show resolved Hide resolved
if _, err := a.CreateUser(ctx); err != nil {
if _, err := a.ProClient().UserCreate(ctx); err != nil {
return sendError(err)
}
return C.CString("true")
Expand Down Expand Up @@ -253,7 +253,7 @@ func deleteAccount(password *C.char) *C.char {
A: A.Bytes(),
}
log.Debugf("Delete Account request email %v A %v", lowerCaseEmail, A.Bytes())
srpB, err := a.AuthClient().LoginPrepare(context.Background(), prepareRequestBody)
srpB, err := a.AuthClient().LoginPrepare(ctx, prepareRequestBody)
if err != nil {
return sendError(err)
}
Expand Down Expand Up @@ -299,7 +299,7 @@ func deleteAccount(password *C.char) *C.char {
if err != nil {
return sendError(err)
}
log.Debugf("Account Delted response %v", isAccountDeleted)
log.Debugf("Account deleted response %v", isAccountDeleted)

if !isAccountDeleted {
return sendError(log.Errorf("user_not_found error while deleting account %v", err))
Expand All @@ -310,8 +310,7 @@ func deleteAccount(password *C.char) *C.char {
// Set user id and token to nil
a.Settings().SetUserIDAndToken(0, "")
// Create new user
// Create new user
if _, err := a.CreateUser(ctx); err != nil {
atavism marked this conversation as resolved.
Show resolved Hide resolved
if _, err := a.ProClient().UserCreate(ctx); err != nil {
return sendError(err)
}
return C.CString("true")
Expand Down
Loading
Loading