Fear: impl google oauth2

pull/21/head
zijiren233 2 years ago
parent 854e78c1f4
commit 9467046f7f

@ -9,7 +9,7 @@ import (
func InitProvider(ctx context.Context) error {
for op, v := range conf.Conf.OAuth2 {
err := provider.InitProvider(op, v.ClientID, v.ClientSecret)
err := provider.InitProvider(op, v.ClientID, v.ClientSecret, provider.WithRedirectURL(v.RedirectURL))
if err != nil {
return err
}

@ -9,13 +9,15 @@ type OAuth2Config map[provider.OAuth2Provider]OAuth2ProviderConfig
type OAuth2ProviderConfig struct {
ClientID string `yaml:"client_id"`
ClientSecret string `yaml:"client_secret"`
RedirectURL string `yaml:"redirect_url"`
}
func DefaultOAuth2Config() OAuth2Config {
return OAuth2Config{
(&provider.GithubProvider{}).Provider(): {
ClientID: "github_client_id",
ClientSecret: "github_client_secret",
ClientID: "",
ClientSecret: "",
RedirectURL: "",
},
}
}

@ -10,25 +10,29 @@ import (
)
type GithubProvider struct {
ClientID, ClientSecret string
config oauth2.Config
}
func (p *GithubProvider) Init(ClientID, ClientSecret string) {
p.ClientID = ClientID
p.ClientSecret = ClientSecret
func (p *GithubProvider) Init(ClientID, ClientSecret string, options ...Oauth2Option) {
p.config.ClientID = ClientID
p.config.ClientSecret = ClientSecret
p.config.Scopes = []string{"user"}
p.config.Endpoint = github.Endpoint
for _, o := range options {
o(&p.config)
}
}
func (p *GithubProvider) Provider() OAuth2Provider {
return "github"
}
func (p *GithubProvider) NewConfig() *oauth2.Config {
return &oauth2.Config{
ClientID: p.ClientID,
ClientSecret: p.ClientSecret,
Scopes: []string{"user"},
Endpoint: github.Endpoint,
func (p *GithubProvider) NewConfig(options ...Oauth2Option) *oauth2.Config {
c := p.config
for _, o := range options {
o(&c)
}
return &c
}
func (p *GithubProvider) GetUserInfo(ctx context.Context, config *oauth2.Config, code string) (*UserInfo, error) {

@ -9,25 +9,29 @@ import (
)
type GitlabProvider struct {
ClientID, ClientSecret string
config oauth2.Config
}
func (g *GitlabProvider) Init(ClientID, ClientSecret string) {
g.ClientID = ClientID
g.ClientSecret = ClientSecret
func (g *GitlabProvider) Init(ClientID, ClientSecret string, options ...Oauth2Option) {
g.config.ClientID = ClientID
g.config.ClientSecret = ClientSecret
g.config.Scopes = []string{"read_user"}
g.config.Endpoint = gitlab.Endpoint
for _, o := range options {
o(&g.config)
}
}
func (g *GitlabProvider) Provider() OAuth2Provider {
return "gitlab"
}
func (g *GitlabProvider) NewConfig() *oauth2.Config {
return &oauth2.Config{
ClientID: g.ClientID,
ClientSecret: g.ClientSecret,
Scopes: []string{"read_user"},
Endpoint: gitlab.Endpoint,
func (g *GitlabProvider) NewConfig(options ...Oauth2Option) *oauth2.Config {
c := g.config
for _, o := range options {
o(&c)
}
return &c
}
func (g *GitlabProvider) GetUserInfo(ctx context.Context, config *oauth2.Config, code string) (*UserInfo, error) {

@ -4,30 +4,35 @@ import (
"context"
"net/http"
json "github.com/json-iterator/go"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
)
type GoogleProvider struct {
ClientID, ClientSecret string
config oauth2.Config
}
func (g *GoogleProvider) Init(ClientID, ClientSecret string) {
g.ClientID = ClientID
g.ClientSecret = ClientSecret
func (g *GoogleProvider) Init(ClientID, ClientSecret string, options ...Oauth2Option) {
g.config.ClientID = ClientID
g.config.ClientSecret = ClientSecret
g.config.Scopes = []string{"profile"}
g.config.Endpoint = google.Endpoint
for _, o := range options {
o(&g.config)
}
}
func (g *GoogleProvider) Provider() OAuth2Provider {
return "google"
}
func (g *GoogleProvider) NewConfig() *oauth2.Config {
return &oauth2.Config{
ClientID: g.ClientID,
ClientSecret: g.ClientSecret,
Scopes: []string{"profile"},
Endpoint: google.Endpoint,
func (g *GoogleProvider) NewConfig(options ...Oauth2Option) *oauth2.Config {
c := g.config
for _, o := range options {
o(&c)
}
return &c
}
func (g *GoogleProvider) GetUserInfo(ctx context.Context, config *oauth2.Config, code string) (*UserInfo, error) {
@ -45,9 +50,22 @@ func (g *GoogleProvider) GetUserInfo(ctx context.Context, config *oauth2.Config,
return nil, err
}
defer resp.Body.Close()
return nil, FormatErrNotImplemented("google")
ui := googleUserInfo{}
err = json.NewDecoder(resp.Body).Decode(&ui)
if err != nil {
return nil, err
}
return &UserInfo{
Username: ui.Name,
ProviderUserID: ui.ID,
}, nil
}
func init() {
registerProvider(new(GoogleProvider))
}
type googleUserInfo struct {
ID uint `json:"id,string"`
Name string `json:"name"`
}

@ -19,19 +19,27 @@ type UserInfo struct {
ProviderUserID uint
}
type Oauth2Option func(*oauth2.Config)
func WithRedirectURL(url string) Oauth2Option {
return func(c *oauth2.Config) {
c.RedirectURL = url
}
}
type ProviderInterface interface {
Init(ClientID, ClientSecret string)
Init(ClientID, ClientSecret string, options ...Oauth2Option)
Provider() OAuth2Provider
NewConfig() *oauth2.Config
NewConfig(options ...Oauth2Option) *oauth2.Config
GetUserInfo(ctx context.Context, config *oauth2.Config, code string) (*UserInfo, error)
}
func InitProvider(p OAuth2Provider, ClientID, ClientSecret string) error {
func InitProvider(p OAuth2Provider, ClientID, ClientSecret string, options ...Oauth2Option) error {
pi, ok := allowedProviders[p]
if !ok {
return FormatErrNotImplemented(p)
}
pi.Init(ClientID, ClientSecret)
pi.Init(ClientID, ClientSecret, options...)
if enabledProviders == nil {
enabledProviders = make(map[OAuth2Provider]ProviderInterface)
}

@ -5,7 +5,6 @@ import (
"time"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"github.com/synctv-org/synctv/internal/op"
"github.com/synctv-org/synctv/internal/provider"
"github.com/synctv-org/synctv/server/middlewares"
@ -16,9 +15,9 @@ import (
// /oauth2/login/:type
func OAuth2(ctx *gin.Context) {
p := provider.OAuth2Provider(ctx.Param("type"))
t := ctx.Param("type")
pi, err := provider.GetProvider(p)
pi, err := provider.GetProvider(provider.OAuth2Provider(t))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
return
@ -31,9 +30,8 @@ func OAuth2(ctx *gin.Context) {
}
func OAuth2Api(ctx *gin.Context) {
p := provider.OAuth2Provider(ctx.Param("type"))
pi, err := provider.GetProvider(p)
t := ctx.Param("type")
pi, err := provider.GetProvider(provider.OAuth2Provider(t))
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
}
@ -48,8 +46,6 @@ func OAuth2Api(ctx *gin.Context) {
// /oauth2/callback/:type
func OAuth2Callback(ctx *gin.Context) {
p := provider.OAuth2Provider(ctx.Param("type"))
code := ctx.Query("code")
if code == "" {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorStringResp("invalid oauth2 code"))
@ -68,6 +64,7 @@ func OAuth2Callback(ctx *gin.Context) {
return
}
p := provider.OAuth2Provider(ctx.Param("type"))
pi, err := provider.GetProvider(p)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
@ -91,15 +88,11 @@ func OAuth2Callback(ctx *gin.Context) {
return
}
logrus.Info("asdasd")
RenderToken(ctx, "/web/", token)
}
// /oauth2/callback/:type
func OAuth2CallbackApi(ctx *gin.Context) {
p := provider.OAuth2Provider(ctx.Param("type"))
req := model.OAuth2CallbackReq{}
if err := req.Decode(ctx); err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))
@ -112,6 +105,7 @@ func OAuth2CallbackApi(ctx *gin.Context) {
return
}
p := provider.OAuth2Provider(ctx.Param("type"))
pi, err := provider.GetProvider(p)
if err != nil {
ctx.AbortWithStatusJSON(http.StatusBadRequest, model.NewApiErrorResp(err))

@ -7,8 +7,17 @@ import (
)
type SyncCache[K comparable, V any] struct {
cache rwmap.RWMap[K, *entry[V]]
ticker *time.Ticker
cache rwmap.RWMap[K, *entry[V]]
deletedCallback func(v V)
ticker *time.Ticker
}
type SyncCacheConfig[K comparable, V any] func(sc *SyncCache[K, V])
func WithDeletedCallback[K comparable, V any](callback func(v V)) SyncCacheConfig[K, V] {
return func(sc *SyncCache[K, V]) {
sc.deletedCallback = callback
}
}
func NewSyncCache[K comparable, V any](trimTime time.Duration) *SyncCache[K, V] {
@ -31,7 +40,10 @@ func (sc *SyncCache[K, V]) Releases() {
func (sc *SyncCache[K, V]) trim() {
sc.cache.Range(func(key K, value *entry[V]) bool {
if value.IsExpired() {
sc.cache.Delete(key)
e, loaded := sc.cache.LoadAndDelete(key)
if loaded && sc.deletedCallback != nil {
sc.deletedCallback(e.value)
}
}
return true
})

Loading…
Cancel
Save