customer/internal/service/oauth/oauth.go
2023-05-16 04:12:34 +03:00

86 lines
2.7 KiB
Go

package oauth
import (
"context"
"github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"penahub.gitlab.yandexcloud.net/pena-services/pena-social-auth/pkg/utils"
)
/*
TODO:
- Реализовать рандомную генерацию state. Каждый раз при генерации ссылки (auth/link),
для этой ссылки должен генерироваться новый state. Так же при реализации этого функционала,
необходимо решить, где хранить этот временный state: MongoDB, Reddis, RAM
- Покрыть тестами генерацию рандомного state
*/
//go:generate mockery --name serviceClient
type serviceClient[T any] interface {
GetUserInformation(ctx context.Context, accessToken string) (*T, error)
}
//go:generate mockery --name oauthClient
type oauthClient interface {
Exchange(ctx context.Context, code string, opts ...oauth2.AuthCodeOption) (*oauth2.Token, error)
AuthCodeURL(state string, opts ...oauth2.AuthCodeOption) string
}
type Deps[T any] struct {
Logger *logrus.Logger
ServiceClient serviceClient[T]
OAuthClient oauthClient
}
type Service[T any] struct {
logger *logrus.Logger
serviceClient serviceClient[T]
oauthClient oauthClient
state string
}
func New[T any](deps *Deps[T]) *Service[T] {
return &Service[T]{
logger: deps.Logger,
serviceClient: deps.ServiceClient,
oauthClient: deps.OAuthClient,
state: utils.GetRandomString(10),
}
}
func (receiver *Service[T]) GetUserInformationByCode(ctx context.Context, code string) (*T, error) {
token, err := receiver.oauthClient.Exchange(ctx, code)
if err != nil {
receiver.logger.Errorf("failed to exchange token on <GetSocialUserInformationByCode> of <AuthService>: %v", err)
return nil, err
}
userInformation, err := receiver.serviceClient.GetUserInformation(ctx, token.AccessToken)
if err != nil {
receiver.logger.Errorf("failed to get user information on <GetSocialUserInformationByCode> of <AuthService>: %v", err)
return nil, err
}
return userInformation, nil
}
func (receiver *Service[any]) GenerateAuthURL() string {
return receiver.oauthClient.AuthCodeURL(receiver.GetState(), oauth2.AccessTypeOffline)
}
func (receiver *Service[any]) GenerateLinkURL(accessToken string) string {
setAccessTokenParam := oauth2.SetAuthURLParam("accessToken", accessToken)
return receiver.oauthClient.AuthCodeURL(receiver.GetState(), oauth2.AccessTypeOffline, setAccessTokenParam)
}
func (receiver *Service[any]) ValidateState(state string) bool {
return state == receiver.state
}
func (receiver *Service[any]) GetState() string {
return receiver.state
}