init push
This commit is contained in:
110
backend/pkg/oauth/oauth.go
Normal file
110
backend/pkg/oauth/oauth.go
Normal file
@@ -0,0 +1,110 @@
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/chaitin/panda-wiki/log"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
logger *log.Logger
|
||||
ctx context.Context
|
||||
config *Config
|
||||
oauth *oauth2.Config
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
const (
|
||||
callbackPath = "/share/pro/v1/openapi/oauth/callback"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
RedirectURI string `json:"redirect_uri,omitempty"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
AuthorizeURL string `json:"authorize_url,omitempty"`
|
||||
TokenURL string `json:"token_url,omitempty"`
|
||||
UserInfoURL string `json:"user_info_url,omitempty"`
|
||||
IDField string `json:"id_field,omitempty"`
|
||||
NameField string `json:"name_field,omitempty"`
|
||||
AvatarField string `json:"avatar_field,omitempty"`
|
||||
EmailField string `json:"email_field,omitempty"`
|
||||
}
|
||||
type UserInfo struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
AvatarUrl string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
// NewClient 创建OAuth客户端
|
||||
func NewClient(ctx context.Context, logger *log.Logger, baseUrl string, config Config) (*Client, error) {
|
||||
redirectURI, err := url.JoinPath(baseUrl, callbackPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{
|
||||
ctx: ctx,
|
||||
logger: logger.WithModule("pkg.oauth"),
|
||||
oauth: &oauth2.Config{
|
||||
ClientID: config.ClientID,
|
||||
ClientSecret: config.ClientSecret,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: config.AuthorizeURL,
|
||||
TokenURL: config.TokenURL,
|
||||
},
|
||||
RedirectURL: redirectURI,
|
||||
Scopes: config.Scopes,
|
||||
},
|
||||
config: &config,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Client) GetAuthorizeURL(state string) string {
|
||||
return c.oauth.AuthCodeURL(state)
|
||||
}
|
||||
|
||||
func (c *Client) GetUserInfo(code string) (*UserInfo, error) {
|
||||
token, err := c.oauth.Exchange(c.ctx, code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := c.oauth.Client(c.ctx, token)
|
||||
res, err := client.Get(c.config.UserInfoURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
buf, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.logger.Info("oauth GetUserInfo:", log.Any("resp", string(buf)))
|
||||
|
||||
jsonString := string(buf)
|
||||
|
||||
email := gjson.Get(jsonString, c.config.EmailField).String()
|
||||
if email == "" && c.config.UserInfoURL == githubUserInfoURL {
|
||||
email, err = c.GetGithubPrimaryEmail(token)
|
||||
if err != nil {
|
||||
c.logger.Warn("GetGithubPrimaryEmail failed", log.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
return &UserInfo{
|
||||
ID: gjson.Get(jsonString, c.config.IDField).String(),
|
||||
AvatarUrl: gjson.Get(jsonString, c.config.AvatarField).String(),
|
||||
Name: gjson.Get(jsonString, c.config.NameField).String(),
|
||||
Email: email,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user