generated from PenaSide/GolangTemplate
86 lines
2.7 KiB
Go
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
|
|
}
|