Skip to content

Commit

Permalink
fix: replace fatal logs with proper error handling
Browse files Browse the repository at this point in the history
- fires nwc shutdown event synchronously
- requires at least one minute leeway for access token expiry
  • Loading branch information
rolznz committed Sep 25, 2024
1 parent ff417c4 commit 74ad3a7
Show file tree
Hide file tree
Showing 14 changed files with 264 additions and 93 deletions.
69 changes: 52 additions & 17 deletions alby/alby_oauth_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ func (svc *albyOAuthService) CallbackHandler(ctx context.Context, code string, l
if err != nil {
logger.Logger.WithError(err).Error("Failed to fetch user me")
// remove token so user can retry
svc.cfg.SetUpdate(accessTokenKey, "", "")
err2 := svc.cfg.SetUpdate(accessTokenKey, "", "")
if err2 != nil {
logger.Logger.WithError(err2).Error("failed to remove existing access token")
}
return err
}

Expand All @@ -109,7 +112,11 @@ func (svc *albyOAuthService) CallbackHandler(ctx context.Context, code string, l

// save the user's alby account ID on first time login
if existingUserIdentifier == "" {
svc.cfg.SetUpdate(userIdentifierKey, me.Identifier, "")
err := svc.cfg.SetUpdate(userIdentifierKey, me.Identifier, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to set user identifier")
return err
}

if svc.cfg.GetEnv().AutoLinkAlbyAccount {
// link account on first login
Expand All @@ -121,7 +128,11 @@ func (svc *albyOAuthService) CallbackHandler(ctx context.Context, code string, l

} else if me.Identifier != existingUserIdentifier {
// remove token so user can retry with correct account
svc.cfg.SetUpdate(accessTokenKey, "", "")
err := svc.cfg.SetUpdate(accessTokenKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to set user access token")
return err
}
return errors.New("Alby Hub is connected to a different alby account. Please log out of your Alby Account at getalby.com and try again.")
}

Expand Down Expand Up @@ -155,9 +166,18 @@ func (svc *albyOAuthService) IsConnected(ctx context.Context) bool {
}

func (svc *albyOAuthService) saveToken(token *oauth2.Token) {
svc.cfg.SetUpdate(accessTokenExpiryKey, strconv.FormatInt(token.Expiry.Unix(), 10), "")
svc.cfg.SetUpdate(accessTokenKey, token.AccessToken, "")
svc.cfg.SetUpdate(refreshTokenKey, token.RefreshToken, "")
err := svc.cfg.SetUpdate(accessTokenExpiryKey, strconv.FormatInt(token.Expiry.Unix(), 10), "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save access token expiry")
}
err = svc.cfg.SetUpdate(accessTokenKey, token.AccessToken, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save access token")
}
err = svc.cfg.SetUpdate(refreshTokenKey, token.RefreshToken, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save refresh token")
}
}

var tokenMutex sync.Mutex
Expand Down Expand Up @@ -202,8 +222,8 @@ func (svc *albyOAuthService) fetchUserToken(ctx context.Context) (*oauth2.Token,
RefreshToken: refreshToken,
}

// only use the current token if it has at least 20 seconds before expiry
if currentToken.Expiry.After(time.Now().Add(time.Duration(20) * time.Second)) {
// only use the current token if it has at least 60 seconds before expiry
if currentToken.Expiry.After(time.Now().Add(time.Duration(60) * time.Second)) {
logger.Logger.Debug("Using existing Alby OAuth token")
return currentToken, nil
}
Expand Down Expand Up @@ -290,7 +310,10 @@ func (svc *albyOAuthService) GetMe(ctx context.Context) (*AlbyMe, error) {
return nil, err
}

svc.cfg.SetUpdate(lightningAddressKey, me.LightningAddress, "")
err = svc.cfg.SetUpdate(lightningAddressKey, me.LightningAddress, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lightning address")
}

logger.Logger.WithFields(logrus.Fields{"me": me}).Info("Alby me response")
return me, nil
Expand Down Expand Up @@ -451,9 +474,6 @@ func (svc *albyOAuthService) SendPayment(ctx context.Context, invoice string) er
}

func (svc *albyOAuthService) GetAuthUrl() string {
if svc.cfg.GetEnv().AlbyClientId == "" || svc.cfg.GetEnv().AlbyClientSecret == "" {
logger.Logger.Fatalf("No ALBY_OAUTH_CLIENT_ID or ALBY_OAUTH_CLIENT_SECRET set")
}
return svc.oauthConf.AuthCodeURL("unused")
}

Expand All @@ -464,11 +484,26 @@ func (svc *albyOAuthService) UnlinkAccount(ctx context.Context) error {
}
svc.deleteAlbyAccountApps()

svc.cfg.SetUpdate(userIdentifierKey, "", "")
svc.cfg.SetUpdate(accessTokenKey, "", "")
svc.cfg.SetUpdate(accessTokenExpiryKey, "", "")
svc.cfg.SetUpdate(refreshTokenKey, "", "")
svc.cfg.SetUpdate(lightningAddressKey, "", "")
err = svc.cfg.SetUpdate(userIdentifierKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove user identifier from config")
}
err = svc.cfg.SetUpdate(accessTokenKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove access token from config")
}
err = svc.cfg.SetUpdate(accessTokenExpiryKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove access token expiry from config")
}
err = svc.cfg.SetUpdate(refreshTokenKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove refresh token from config")
}
err = svc.cfg.SetUpdate(lightningAddressKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove lightning address from config")
}

return nil
}
Expand Down
83 changes: 67 additions & 16 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,10 @@ func (api *api) GetNewOnchainAddress(ctx context.Context) (string, error) {
return "", err
}

api.cfg.SetUpdate(config.OnchainAddressKey, address, "")
err = api.cfg.SetUpdate(config.OnchainAddressKey, address, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save new onchain address to config")
}

return address, nil
}
Expand Down Expand Up @@ -706,7 +709,10 @@ func (api *api) GetMnemonic(unlockPassword string) (*MnemonicResponse, error) {
}

func (api *api) SetNextBackupReminder(backupReminderRequest *BackupReminderRequest) error {
api.cfg.SetUpdate("NextBackupReminder", backupReminderRequest.NextBackupReminder, "")
err := api.cfg.SetUpdate("NextBackupReminder", backupReminderRequest.NextBackupReminder, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save next backup reminder to config")
}
return nil
}

Expand Down Expand Up @@ -751,44 +757,89 @@ func (api *api) Setup(ctx context.Context, setupRequest *SetupRequest) error {
return errors.New("no unlock password provided")
}

api.cfg.Setup(setupRequest.UnlockPassword)

// TODO: move all below code to cfg.Setup()
err = api.cfg.Setup(setupRequest.UnlockPassword)
if err != nil {
return err
}

// update next backup reminder
api.cfg.SetUpdate("NextBackupReminder", setupRequest.NextBackupReminder, "")
err = api.cfg.SetUpdate("NextBackupReminder", setupRequest.NextBackupReminder, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save next backup reminder")
}

// only update non-empty values
if setupRequest.LNBackendType != "" {
api.cfg.SetUpdate("LNBackendType", setupRequest.LNBackendType, "")
err = api.cfg.SetUpdate("LNBackendType", setupRequest.LNBackendType, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save backend type")
return err
}
}
if setupRequest.BreezAPIKey != "" {
api.cfg.SetUpdate("BreezAPIKey", setupRequest.BreezAPIKey, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("BreezAPIKey", setupRequest.BreezAPIKey, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save breez api key")
return err
}
}
if setupRequest.Mnemonic != "" {
api.cfg.SetUpdate("Mnemonic", setupRequest.Mnemonic, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("Mnemonic", setupRequest.Mnemonic, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save encrypted mnemonic")
return err
}
}
if setupRequest.GreenlightInviteCode != "" {
api.cfg.SetUpdate("GreenlightInviteCode", setupRequest.GreenlightInviteCode, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("GreenlightInviteCode", setupRequest.GreenlightInviteCode, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save greenlight invite code")
return err
}
}
if setupRequest.LNDAddress != "" {
api.cfg.SetUpdate("LNDAddress", setupRequest.LNDAddress, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("LNDAddress", setupRequest.LNDAddress, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lnd address")
return err
}
}
if setupRequest.LNDCertHex != "" {
api.cfg.SetUpdate("LNDCertHex", setupRequest.LNDCertHex, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("LNDCertHex", setupRequest.LNDCertHex, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lnd cert hex")
return err
}
}
if setupRequest.LNDMacaroonHex != "" {
api.cfg.SetUpdate("LNDMacaroonHex", setupRequest.LNDMacaroonHex, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("LNDMacaroonHex", setupRequest.LNDMacaroonHex, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lnd macaroon hex")
return err
}
}

if setupRequest.PhoenixdAddress != "" {
api.cfg.SetUpdate("PhoenixdAddress", setupRequest.PhoenixdAddress, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("PhoenixdAddress", setupRequest.PhoenixdAddress, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save phoenix address")
return err
}
}
if setupRequest.PhoenixdAuthorization != "" {
api.cfg.SetUpdate("PhoenixdAuthorization", setupRequest.PhoenixdAuthorization, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("PhoenixdAuthorization", setupRequest.PhoenixdAuthorization, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save phoenix auth")
return err
}
}

if setupRequest.CashuMintUrl != "" {
api.cfg.SetUpdate("CashuMintUrl", setupRequest.CashuMintUrl, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("CashuMintUrl", setupRequest.CashuMintUrl, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save cashu mint url")
return err
}
}

return nil
Expand Down
7 changes: 4 additions & 3 deletions cmd/http/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ func main() {

// Create a channel to receive OS signals.
osSignalChannel := make(chan os.Signal, 1)
// Notify the channel on os.Interrupt, syscall.SIGTERM, and os.Kill.
signal.Notify(osSignalChannel, os.Interrupt, syscall.SIGTERM, os.Kill)
// Notify the channel on os.Interrupt, syscall.SIGTERM. os.Kill cannot be caught.
signal.Notify(osSignalChannel, os.Interrupt, syscall.SIGTERM)

ctx, cancel := context.WithCancel(context.Background())
svc, _ := service.NewService(ctx)
Expand All @@ -35,7 +35,8 @@ func main() {
//start Echo server
go func() {
if err := e.Start(fmt.Sprintf(":%v", svc.GetConfig().GetEnv().Port)); err != nil && err != nethttp.ErrServerClosed {
logger.Logger.Fatalf("shutting down the server: %v", err)
logger.Logger.WithError(err).Error("echo server failed to start")
ctx.Done()
}
}()

Expand Down
Loading

0 comments on commit 74ad3a7

Please sign in to comment.