Feat: oauth2 qq

pull/31/head v0.3.0-alpha-2
zijiren233 2 years ago
parent 1bb24e7382
commit c96abd2927

@ -19,7 +19,7 @@ func WithRole(role model.Role) CreateUserConfig {
} }
} }
func CreateUser(username string, p provider.OAuth2Provider, puid uint, conf ...CreateUserConfig) (*model.User, error) { func CreateUser(username string, p provider.OAuth2Provider, puid uint64, conf ...CreateUserConfig) (*model.User, error) {
u := &model.User{ u := &model.User{
Username: username, Username: username,
Role: model.RoleUser, Role: model.RoleUser,
@ -41,7 +41,7 @@ func CreateUser(username string, p provider.OAuth2Provider, puid uint, conf ...C
} }
// 只有当provider和puid没有找到对应的user时才会创建 // 只有当provider和puid没有找到对应的user时才会创建
func CreateOrLoadUser(username string, p provider.OAuth2Provider, puid uint, conf ...CreateUserConfig) (*model.User, error) { func CreateOrLoadUser(username string, p provider.OAuth2Provider, puid uint64, conf ...CreateUserConfig) (*model.User, error) {
var user model.User var user model.User
var userProvider model.UserProvider var userProvider model.UserProvider
@ -60,7 +60,7 @@ func CreateOrLoadUser(username string, p provider.OAuth2Provider, puid uint, con
return &user, nil return &user, nil
} }
func GetProviderUserID(p provider.OAuth2Provider, puid uint) (string, error) { func GetProviderUserID(p provider.OAuth2Provider, puid uint64) (string, error) {
var userProvider model.UserProvider var userProvider model.UserProvider
if err := db.Where("provider = ? AND provider_user_id = ?", p, puid).First(&userProvider).Error; err != nil { if err := db.Where("provider = ? AND provider_user_id = ?", p, puid).First(&userProvider).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {

@ -8,7 +8,7 @@ import (
type UserProvider struct { type UserProvider struct {
Provider provider.OAuth2Provider `gorm:"not null;primarykey"` Provider provider.OAuth2Provider `gorm:"not null;primarykey"`
ProviderUserID uint `gorm:"not null;primarykey;autoIncrement:false"` ProviderUserID uint64 `gorm:"not null;primarykey;autoIncrement:false"`
CreatedAt time.Time CreatedAt time.Time
UpdatedAt time.Time UpdatedAt time.Time
UserID string `gorm:"not null;index"` UserID string `gorm:"not null;index"`

@ -43,7 +43,7 @@ func GetUserById(id string) (*User, error) {
return u2, userCache.SetWithExpire(id, u2, time.Hour) return u2, userCache.SetWithExpire(id, u2, time.Hour)
} }
func CreateUser(username string, p provider.OAuth2Provider, pid uint, conf ...db.CreateUserConfig) (*User, error) { func CreateUser(username string, p provider.OAuth2Provider, pid uint64, conf ...db.CreateUserConfig) (*User, error) {
if username == "" { if username == "" {
return nil, errors.New("username cannot be empty") return nil, errors.New("username cannot be empty")
} }
@ -59,7 +59,7 @@ func CreateUser(username string, p provider.OAuth2Provider, pid uint, conf ...db
return u2, userCache.SetWithExpire(u.ID, u2, time.Hour) return u2, userCache.SetWithExpire(u.ID, u2, time.Hour)
} }
func CreateOrLoadUser(username string, p provider.OAuth2Provider, pid uint, conf ...db.CreateUserConfig) (*User, error) { func CreateOrLoadUser(username string, p provider.OAuth2Provider, pid uint64, conf ...db.CreateUserConfig) (*User, error) {
if username == "" { if username == "" {
return nil, errors.New("username cannot be empty") return nil, errors.New("username cannot be empty")
} }
@ -75,7 +75,7 @@ func CreateOrLoadUser(username string, p provider.OAuth2Provider, pid uint, conf
return u2, userCache.SetWithExpire(u.ID, u2, time.Hour) return u2, userCache.SetWithExpire(u.ID, u2, time.Hour)
} }
func GetUserByProvider(p provider.OAuth2Provider, pid uint) (*User, error) { func GetUserByProvider(p provider.OAuth2Provider, pid uint64) (*User, error) {
uid, err := db.GetProviderUserID(p, pid) uid, err := db.GetProviderUserID(p, pid)
if err != nil { if err != nil {
return nil, err return nil, err

@ -79,6 +79,6 @@ func (c *GRPCClient) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provid
} }
return &provider.UserInfo{ return &provider.UserInfo{
Username: resp.Username, Username: resp.Username,
ProviderUserID: uint(resp.ProviderUserId), ProviderUserID: resp.ProviderUserId,
}, nil }, nil
} }

@ -80,7 +80,7 @@ func (p *GiteeProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*pro
} }
type giteeUserInfo struct { type giteeUserInfo struct {
ID uint `json:"id"` ID uint64 `json:"id"`
Login string `json:"login"` Login string `json:"login"`
} }

@ -10,7 +10,7 @@ type OAuth2Provider string
type UserInfo struct { type UserInfo struct {
Username string Username string
ProviderUserID uint ProviderUserID uint64
} }
type Oauth2Option struct { type Oauth2Option struct {

@ -71,7 +71,7 @@ type baiduNetDiskProviderUserInfo struct {
BaiduName string `json:"baidu_name"` BaiduName string `json:"baidu_name"`
Errmsg string `json:"errmsg"` Errmsg string `json:"errmsg"`
Errno int `json:"errno"` Errno int `json:"errno"`
Uk uint `json:"uk"` Uk uint64 `json:"uk"`
} }
func init() { func init() {

@ -3,12 +3,11 @@ package providers
import ( import (
"context" "context"
"fmt" "fmt"
"hash/crc32" "hash/crc64"
"net/http" "net/http"
json "github.com/json-iterator/go" json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider" "github.com/synctv-org/synctv/internal/provider"
"github.com/zijiren233/stream"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )
@ -62,7 +61,7 @@ func (p *BaiduProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*pro
} }
return &provider.UserInfo{ return &provider.UserInfo{
Username: ui.Uname, Username: ui.Uname,
ProviderUserID: uint(crc32.ChecksumIEEE(stream.StringToBytes(ui.Openid))), ProviderUserID: crc64.Checksum([]byte(ui.Openid), crc64.MakeTable(crc64.ECMA)),
}, nil }, nil
} }

@ -63,7 +63,7 @@ func (p *GiteeProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*pro
} }
type giteeUserInfo struct { type giteeUserInfo struct {
ID uint `json:"id"` ID uint64 `json:"id"`
Login string `json:"login"` Login string `json:"login"`
} }

@ -62,7 +62,7 @@ func (p *GithubProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*pr
type githubUserInfo struct { type githubUserInfo struct {
Login string `json:"login"` Login string `json:"login"`
ID uint `json:"id"` ID uint64 `json:"id"`
} }
func init() { func init() {

@ -65,6 +65,6 @@ func init() {
} }
type googleUserInfo struct { type googleUserInfo struct {
ID uint `json:"id,string"` ID uint64 `json:"id,string"`
Name string `json:"name"` Name string `json:"name"`
} }

@ -2,7 +2,7 @@ package providers
import ( import (
"context" "context"
"hash/crc32" "hash/crc64"
"net/http" "net/http"
json "github.com/json-iterator/go" json "github.com/json-iterator/go"
@ -58,7 +58,7 @@ func (p *MicrosoftProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (
} }
return &provider.UserInfo{ return &provider.UserInfo{
Username: ui.DisplayName, Username: ui.DisplayName,
ProviderUserID: uint(crc32.ChecksumIEEE(stream.StringToBytes(ui.ID))), ProviderUserID: crc64.Checksum(stream.StringToBytes(ui.ID), crc64.MakeTable(crc64.ECMA)),
}, nil }, nil
} }

@ -0,0 +1,74 @@
package providers
import (
"context"
"fmt"
"net/http"
"strconv"
json "github.com/json-iterator/go"
"github.com/synctv-org/synctv/internal/provider"
"golang.org/x/oauth2"
)
type QQProvider struct {
config oauth2.Config
}
func (p *QQProvider) Init(c provider.Oauth2Option) {
p.config.Scopes = []string{"get_user_info"}
p.config.Endpoint = oauth2.Endpoint{
AuthURL: "https://graph.qq.com/oauth2.0/authorize",
TokenURL: "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code",
}
p.config.ClientID = c.ClientID
p.config.ClientSecret = c.ClientSecret
p.config.RedirectURL = c.RedirectURL
}
func (p *QQProvider) Provider() provider.OAuth2Provider {
return "qq"
}
func (p *QQProvider) NewAuthURL(state string) string {
return p.config.AuthCodeURL(state, oauth2.AccessTypeOnline)
}
func (p *QQProvider) GetToken(ctx context.Context, code string) (*oauth2.Token, error) {
return p.config.Exchange(ctx, code)
}
func (p *QQProvider) RefreshToken(ctx context.Context, tk string) (*oauth2.Token, error) {
return p.config.TokenSource(ctx, &oauth2.Token{RefreshToken: tk}).Token()
}
func (p *QQProvider) GetUserInfo(ctx context.Context, tk *oauth2.Token) (*provider.UserInfo, error) {
client := p.config.Client(ctx, tk)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("https://graph.qq.com/oauth2.0/me?access_token=%s&fmt=json", tk.AccessToken), nil)
if err != nil {
return nil, err
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
ui := qqProviderUserInfo{}
err = json.NewDecoder(resp.Body).Decode(&ui)
if err != nil {
return nil, err
}
return &provider.UserInfo{
Username: strconv.FormatUint(ui.Openid, 10),
ProviderUserID: ui.Openid,
}, nil
}
func init() {
RegisterProvider(new(QQProvider))
}
type qqProviderUserInfo struct {
ClientID string `json:"client_id"`
Openid uint64 `json:"openid,string"`
}
Loading…
Cancel
Save