在嵌套函数中设置值
Setting a value within a nested function
给了这个golang代码,因为我的golang生锈了,所以很难自由批评。基本的刷新令牌流程,但是我们将函数包装在 TX 函数中,以便在刷新流程出现问题时允许回滚。
我们需要 return newToken
值,但是它只保存我们在 refresh
函数期间需要的值,当它 return 到 refreshToken 取决于我是否通过它一个对象或指针分别是 returns 新的空标记或 nil。
package service
import (
"context"
"database/sql"
"errors"
"strings"
"github.com/api-oauth/pkg/models"
"github.com/api-oauth/pkg/repository"
"golang.org/x/oauth2"
)
const minParts = 2
type OAuthAPI interface {
Exchange(context.Context, string) (*oauth2.Token, error)
Refresh(context.Context, string) (*oauth2.Token, error)
}
type Service struct {
repo repository.RepoInterface
oauthAPI OAuthAPI
}
func New(api OAuthAPI, repo repository.RepoInterface) *Service {
return &Service{repo: repo, oauthAPI: api}
}
var (
ErrNoRefreshTokenFound = errors.New("no refresh token found")
errNoScopesReturn = errors.New("no scopes returned")
errNoProfileFound = errors.New("no profile found")
)
func (s *Service) RefreshToken(ctx context.Context, clientID string, userID int64) (*oauth2.Token, error) {
var newToken *oauth2.Token
err := s.repo.InTx(s.refresh(ctx, clientID, userID, newToken))
if err != nil {
return nil, err
}
return newToken, nil
}
func (s *Service) refresh(ctx context.Context, clientID string, userID int64, newToken *oauth2.Token) func(repo repository.Auth) error {
return func(repo repository.Auth) error {
oldToken, err := repo.GetToken(ctx, userID, clientID)
if err != nil && err != sql.ErrNoRows {
return err
}
if oldToken == nil {
return ErrNoRefreshTokenFound
}
newToken, err = s.oauthAPI.Refresh(ctx, oldToken.Refresh)
if err != nil {
return err
}
rec := models.TokenRecord{
UserID: userID,
ClientID: clientID,
ProfileID: oldToken.ProfileID,
Access: newToken.AccessToken,
Refresh: newToken.RefreshToken,
Expiry: newToken.Expiry,
}
err = repo.UpdateToken(ctx, &rec)
if err != nil {
return err
}
return nil
}
}
正在尝试 RefreshToken
return 更新的令牌信息
传递newToken
的地址:
func (s *Service) RefreshToken(ctx context.Context, clientID string, userID int64) (*oauth2.Token, error) {
var newToken *oauth2.Token
err := s.repo.InTx(s.refresh(ctx, clientID, userID, &newToken))
...
然后,将 refresh
函数更改为:
func (s *Service) refresh(ctx context.Context, clientID string, userID int64, newToken **oauth2.Token) func(repo repository.Auth) error {
...
*newToken, err=...
给了这个golang代码,因为我的golang生锈了,所以很难自由批评。基本的刷新令牌流程,但是我们将函数包装在 TX 函数中,以便在刷新流程出现问题时允许回滚。
我们需要 return newToken
值,但是它只保存我们在 refresh
函数期间需要的值,当它 return 到 refreshToken 取决于我是否通过它一个对象或指针分别是 returns 新的空标记或 nil。
package service
import (
"context"
"database/sql"
"errors"
"strings"
"github.com/api-oauth/pkg/models"
"github.com/api-oauth/pkg/repository"
"golang.org/x/oauth2"
)
const minParts = 2
type OAuthAPI interface {
Exchange(context.Context, string) (*oauth2.Token, error)
Refresh(context.Context, string) (*oauth2.Token, error)
}
type Service struct {
repo repository.RepoInterface
oauthAPI OAuthAPI
}
func New(api OAuthAPI, repo repository.RepoInterface) *Service {
return &Service{repo: repo, oauthAPI: api}
}
var (
ErrNoRefreshTokenFound = errors.New("no refresh token found")
errNoScopesReturn = errors.New("no scopes returned")
errNoProfileFound = errors.New("no profile found")
)
func (s *Service) RefreshToken(ctx context.Context, clientID string, userID int64) (*oauth2.Token, error) {
var newToken *oauth2.Token
err := s.repo.InTx(s.refresh(ctx, clientID, userID, newToken))
if err != nil {
return nil, err
}
return newToken, nil
}
func (s *Service) refresh(ctx context.Context, clientID string, userID int64, newToken *oauth2.Token) func(repo repository.Auth) error {
return func(repo repository.Auth) error {
oldToken, err := repo.GetToken(ctx, userID, clientID)
if err != nil && err != sql.ErrNoRows {
return err
}
if oldToken == nil {
return ErrNoRefreshTokenFound
}
newToken, err = s.oauthAPI.Refresh(ctx, oldToken.Refresh)
if err != nil {
return err
}
rec := models.TokenRecord{
UserID: userID,
ClientID: clientID,
ProfileID: oldToken.ProfileID,
Access: newToken.AccessToken,
Refresh: newToken.RefreshToken,
Expiry: newToken.Expiry,
}
err = repo.UpdateToken(ctx, &rec)
if err != nil {
return err
}
return nil
}
}
正在尝试 RefreshToken
return 更新的令牌信息
传递newToken
的地址:
func (s *Service) RefreshToken(ctx context.Context, clientID string, userID int64) (*oauth2.Token, error) {
var newToken *oauth2.Token
err := s.repo.InTx(s.refresh(ctx, clientID, userID, &newToken))
...
然后,将 refresh
函数更改为:
func (s *Service) refresh(ctx context.Context, clientID string, userID int64, newToken **oauth2.Token) func(repo repository.Auth) error {
...
*newToken, err=...