|  | @@ -6,36 +6,20 @@ package user
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import (
 | 
	
		
			
				|  |  |  	"encoding/json"
 | 
	
		
			
				|  |  | +	"errors"
 | 
	
		
			
				|  |  |  	"fmt"
 | 
	
		
			
				|  |  | -	"net/http"
 | 
	
		
			
				|  |  |  	"net/url"
 | 
	
		
			
				|  |  | -	"strconv"
 | 
	
		
			
				|  |  |  	"strings"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	"code.google.com/p/goauth2/oauth"
 | 
	
		
			
				|  |  |  	"github.com/go-martini/martini"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	"github.com/gogits/gogs/models"
 | 
	
		
			
				|  |  |  	"github.com/gogits/gogs/modules/base"
 | 
	
		
			
				|  |  |  	"github.com/gogits/gogs/modules/log"
 | 
	
		
			
				|  |  |  	"github.com/gogits/gogs/modules/middleware"
 | 
	
		
			
				|  |  | +	"github.com/gogits/gogs/modules/social"
 | 
	
		
			
				|  |  |  )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -type BasicUserInfo struct {
 | 
	
		
			
				|  |  | -	Identity string
 | 
	
		
			
				|  |  | -	Name     string
 | 
	
		
			
				|  |  | -	Email    string
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type SocialConnector interface {
 | 
	
		
			
				|  |  | -	Type() int
 | 
	
		
			
				|  |  | -	SetRedirectUrl(string)
 | 
	
		
			
				|  |  | -	UserInfo(*oauth.Token, *url.URL) (*BasicUserInfo, error)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	AuthCodeURL(string) string
 | 
	
		
			
				|  |  | -	Exchange(string) (*oauth.Token, error)
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  func extractPath(next string) string {
 | 
	
		
			
				|  |  |  	n, err := url.Parse(next)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
	
		
			
				|  | @@ -44,278 +28,72 @@ func extractPath(next string) string {
 | 
	
		
			
				|  |  |  	return n.Path
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var (
 | 
	
		
			
				|  |  | -	SocialBaseUrl = "/user/login"
 | 
	
		
			
				|  |  | -	SocialMap     = make(map[string]SocialConnector)
 | 
	
		
			
				|  |  | -)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// github && google && ...
 | 
	
		
			
				|  |  | -func SocialSignIn(params martini.Params, ctx *middleware.Context) {
 | 
	
		
			
				|  |  | -	if base.OauthService == nil || !base.OauthService.GitHub.Enabled {
 | 
	
		
			
				|  |  | -		ctx.Handle(404, "social login not enabled", nil)
 | 
	
		
			
				|  |  | +func SocialSignIn(ctx *middleware.Context, params martini.Params) {
 | 
	
		
			
				|  |  | +	if base.OauthService == nil {
 | 
	
		
			
				|  |  | +		ctx.Handle(404, "social.SocialSignIn(oauth service not enabled)", nil)
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	next := extractPath(ctx.Query("next"))
 | 
	
		
			
				|  |  |  	name := params["name"]
 | 
	
		
			
				|  |  | -	connect, ok := SocialMap[name]
 | 
	
		
			
				|  |  | +	connect, ok := social.SocialMap[name]
 | 
	
		
			
				|  |  |  	if !ok {
 | 
	
		
			
				|  |  | -		ctx.Handle(404, "social login", nil)
 | 
	
		
			
				|  |  | +		ctx.Handle(404, "social.SocialSignIn(social login not enabled)", errors.New(name))
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	code := ctx.Query("code")
 | 
	
		
			
				|  |  |  	if code == "" {
 | 
	
		
			
				|  |  |  		// redirect to social login page
 | 
	
		
			
				|  |  | -		connect.SetRedirectUrl(strings.TrimSuffix(base.AppUrl, "/") + ctx.Req.URL.Host + ctx.Req.URL.Path)
 | 
	
		
			
				|  |  | +		connect.SetRedirectUrl(strings.TrimSuffix(base.AppUrl, "/") + ctx.Req.URL.Path)
 | 
	
		
			
				|  |  |  		ctx.Redirect(connect.AuthCodeURL(next))
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	// handle call back
 | 
	
		
			
				|  |  | -	tk, err := connect.Exchange(code) // exchange for token
 | 
	
		
			
				|  |  | +	tk, err := connect.Exchange(code)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  | -		log.Error("oauth2 handle callback error: %v", err)
 | 
	
		
			
				|  |  | -		ctx.Handle(500, "exchange code error", nil)
 | 
	
		
			
				|  |  | +		ctx.Handle(500, "social.SocialSignIn(Exchange)", err)
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  	next = extractPath(ctx.Query("state"))
 | 
	
		
			
				|  |  | -	log.Trace("success get token")
 | 
	
		
			
				|  |  | +	log.Trace("social.SocialSignIn(Got token)")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	ui, err := connect.UserInfo(tk, ctx.Req.URL)
 | 
	
		
			
				|  |  |  	if err != nil {
 | 
	
		
			
				|  |  | -		ctx.Handle(500, fmt.Sprintf("get infomation from %s error: %v", name, err), nil)
 | 
	
		
			
				|  |  | -		log.Error("social connect error: %s", err)
 | 
	
		
			
				|  |  | +		ctx.Handle(500, fmt.Sprintf("social.SocialSignIn(get info from %s)", name), err)
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | -	log.Info("social login: %s", ui)
 | 
	
		
			
				|  |  | +	log.Info("social.SocialSignIn(social login): %s", ui)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	oa, err := models.GetOauth2(ui.Identity)
 | 
	
		
			
				|  |  |  	switch err {
 | 
	
		
			
				|  |  |  	case nil:
 | 
	
		
			
				|  |  |  		ctx.Session.Set("userId", oa.User.Id)
 | 
	
		
			
				|  |  |  		ctx.Session.Set("userName", oa.User.Name)
 | 
	
		
			
				|  |  | -	case models.ErrOauth2RecordNotExists:
 | 
	
		
			
				|  |  | -		oa = &models.Oauth2{}
 | 
	
		
			
				|  |  | -		raw, _ := json.Marshal(tk) // json encode
 | 
	
		
			
				|  |  | -		oa.Token = string(raw)
 | 
	
		
			
				|  |  | -		oa.Uid = -1
 | 
	
		
			
				|  |  | -		oa.Type = connect.Type()
 | 
	
		
			
				|  |  | -		oa.Identity = ui.Identity
 | 
	
		
			
				|  |  | -		log.Trace("oa: %v", oa)
 | 
	
		
			
				|  |  | +	case models.ErrOauth2RecordNotExist:
 | 
	
		
			
				|  |  | +		raw, _ := json.Marshal(tk)
 | 
	
		
			
				|  |  | +		oa = &models.Oauth2{
 | 
	
		
			
				|  |  | +			Uid:      -1,
 | 
	
		
			
				|  |  | +			Type:     connect.Type(),
 | 
	
		
			
				|  |  | +			Identity: ui.Identity,
 | 
	
		
			
				|  |  | +			Token:    string(raw),
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		log.Trace("social.SocialSignIn(oa): %v", oa)
 | 
	
		
			
				|  |  |  		if err = models.AddOauth2(oa); err != nil {
 | 
	
		
			
				|  |  | -			log.Error("add oauth2 %v", err) // 501
 | 
	
		
			
				|  |  | +			log.Error("social.SocialSignIn(add oauth2): %v", err) // 501
 | 
	
		
			
				|  |  |  			return
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -	case models.ErrOauth2NotAssociatedWithUser:
 | 
	
		
			
				|  |  | +	case models.ErrOauth2NotAssociated:
 | 
	
		
			
				|  |  |  		next = "/user/sign_up"
 | 
	
		
			
				|  |  |  	default:
 | 
	
		
			
				|  |  | -		log.Error("other error: %v", err)
 | 
	
		
			
				|  |  | -		ctx.Handle(500, err.Error(), nil)
 | 
	
		
			
				|  |  | +		ctx.Handle(500, "social.SocialSignIn(GetOauth2)", err)
 | 
	
		
			
				|  |  |  		return
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	ctx.Session.Set("socialId", oa.Id)
 | 
	
		
			
				|  |  |  	ctx.Session.Set("socialName", ui.Name)
 | 
	
		
			
				|  |  |  	ctx.Session.Set("socialEmail", ui.Email)
 | 
	
		
			
				|  |  | -	log.Trace("socialId: %v", oa.Id)
 | 
	
		
			
				|  |  | +	log.Trace("social.SocialSignIn(social ID): %v", oa.Id)
 | 
	
		
			
				|  |  |  	ctx.Redirect(next)
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -//   ________.__  __     ___ ___      ___.
 | 
	
		
			
				|  |  | -//  /  _____/|__|/  |_  /   |   \ __ _\_ |__
 | 
	
		
			
				|  |  | -// /   \  ___|  \   __\/    ~    \  |  \ __ \
 | 
	
		
			
				|  |  | -// \    \_\  \  ||  |  \    Y    /  |  / \_\ \
 | 
	
		
			
				|  |  | -//  \______  /__||__|   \___|_  /|____/|___  /
 | 
	
		
			
				|  |  | -//         \/                 \/           \/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type SocialGithub struct {
 | 
	
		
			
				|  |  | -	Token *oauth.Token
 | 
	
		
			
				|  |  | -	*oauth.Transport
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialGithub) Type() int {
 | 
	
		
			
				|  |  | -	return models.OT_GITHUB
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func init() {
 | 
	
		
			
				|  |  | -	github := &SocialGithub{}
 | 
	
		
			
				|  |  | -	name := "github"
 | 
	
		
			
				|  |  | -	config := &oauth.Config{
 | 
	
		
			
				|  |  | -		ClientId:     "09383403ff2dc16daaa1",                                       //base.OauthService.GitHub.ClientId, // FIXME: panic when set
 | 
	
		
			
				|  |  | -		ClientSecret: "0e4aa0c3630df396cdcea01a9d45cacf79925fea",                   //base.OauthService.GitHub.ClientSecret,
 | 
	
		
			
				|  |  | -		RedirectURL:  strings.TrimSuffix(base.AppUrl, "/") + "/user/login/" + name, //ctx.Req.URL.RequestURI(),
 | 
	
		
			
				|  |  | -		Scope:        "https://api.github.com/user",
 | 
	
		
			
				|  |  | -		AuthURL:      "https://github.com/login/oauth/authorize",
 | 
	
		
			
				|  |  | -		TokenURL:     "https://github.com/login/oauth/access_token",
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	github.Transport = &oauth.Transport{
 | 
	
		
			
				|  |  | -		Config:    config,
 | 
	
		
			
				|  |  | -		Transport: http.DefaultTransport,
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	SocialMap[name] = github
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialGithub) SetRedirectUrl(url string) {
 | 
	
		
			
				|  |  | -	s.Transport.Config.RedirectURL = url
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
 | 
	
		
			
				|  |  | -	transport := &oauth.Transport{
 | 
	
		
			
				|  |  | -		Token: token,
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	var data struct {
 | 
	
		
			
				|  |  | -		Id    int    `json:"id"`
 | 
	
		
			
				|  |  | -		Name  string `json:"login"`
 | 
	
		
			
				|  |  | -		Email string `json:"email"`
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	var err error
 | 
	
		
			
				|  |  | -	r, err := transport.Client().Get(s.Transport.Scope)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	defer r.Body.Close()
 | 
	
		
			
				|  |  | -	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return &BasicUserInfo{
 | 
	
		
			
				|  |  | -		Identity: strconv.Itoa(data.Id),
 | 
	
		
			
				|  |  | -		Name:     data.Name,
 | 
	
		
			
				|  |  | -		Email:    data.Email,
 | 
	
		
			
				|  |  | -	}, nil
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -//   ________                     .__
 | 
	
		
			
				|  |  | -//  /  _____/  ____   ____   ____ |  |   ____
 | 
	
		
			
				|  |  | -// /   \  ___ /  _ \ /  _ \ / ___\|  | _/ __ \
 | 
	
		
			
				|  |  | -// \    \_\  (  <_> |  <_> ) /_/  >  |_\  ___/
 | 
	
		
			
				|  |  | -//  \______  /\____/ \____/\___  /|____/\___  >
 | 
	
		
			
				|  |  | -//         \/             /_____/           \/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type SocialGoogle struct {
 | 
	
		
			
				|  |  | -	Token *oauth.Token
 | 
	
		
			
				|  |  | -	*oauth.Transport
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialGoogle) Type() int {
 | 
	
		
			
				|  |  | -	return models.OT_GOOGLE
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func init() {
 | 
	
		
			
				|  |  | -	google := &SocialGoogle{}
 | 
	
		
			
				|  |  | -	name := "google"
 | 
	
		
			
				|  |  | -	// get client id and secret from
 | 
	
		
			
				|  |  | -	// https://console.developers.google.com/project
 | 
	
		
			
				|  |  | -	config := &oauth.Config{
 | 
	
		
			
				|  |  | -		ClientId:     "849753812404-mpd7ilvlb8c7213qn6bre6p6djjskti9.apps.googleusercontent.com", //base.OauthService.GitHub.ClientId, // FIXME: panic when set
 | 
	
		
			
				|  |  | -		ClientSecret: "VukKc4MwaJUSmiyv3D7ANVCa",                                                 //base.OauthService.GitHub.ClientSecret,
 | 
	
		
			
				|  |  | -		Scope:        "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
 | 
	
		
			
				|  |  | -		AuthURL:      "https://accounts.google.com/o/oauth2/auth",
 | 
	
		
			
				|  |  | -		TokenURL:     "https://accounts.google.com/o/oauth2/token",
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	google.Transport = &oauth.Transport{
 | 
	
		
			
				|  |  | -		Config:    config,
 | 
	
		
			
				|  |  | -		Transport: http.DefaultTransport,
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	SocialMap[name] = google
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialGoogle) SetRedirectUrl(url string) {
 | 
	
		
			
				|  |  | -	s.Transport.Config.RedirectURL = url
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
 | 
	
		
			
				|  |  | -	transport := &oauth.Transport{Token: token}
 | 
	
		
			
				|  |  | -	var data struct {
 | 
	
		
			
				|  |  | -		Id    string `json:"id"`
 | 
	
		
			
				|  |  | -		Name  string `json:"name"`
 | 
	
		
			
				|  |  | -		Email string `json:"email"`
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	var err error
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
 | 
	
		
			
				|  |  | -	r, err := transport.Client().Get(reqUrl)
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	defer r.Body.Close()
 | 
	
		
			
				|  |  | -	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return &BasicUserInfo{
 | 
	
		
			
				|  |  | -		Identity: data.Id,
 | 
	
		
			
				|  |  | -		Name:     data.Name,
 | 
	
		
			
				|  |  | -		Email:    data.Email,
 | 
	
		
			
				|  |  | -	}, nil
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// ________   ________
 | 
	
		
			
				|  |  | -// \_____  \  \_____  \
 | 
	
		
			
				|  |  | -//  /  / \  \  /  / \  \
 | 
	
		
			
				|  |  | -// /   \_/.  \/   \_/.  \
 | 
	
		
			
				|  |  | -// \_____\ \_/\_____\ \_/
 | 
	
		
			
				|  |  | -//        \__>       \__>
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -type SocialQQ struct {
 | 
	
		
			
				|  |  | -	Token *oauth.Token
 | 
	
		
			
				|  |  | -	*oauth.Transport
 | 
	
		
			
				|  |  | -	reqUrl string
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialQQ) Type() int {
 | 
	
		
			
				|  |  | -	return models.OT_QQ
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func init() {
 | 
	
		
			
				|  |  | -	qq := &SocialQQ{}
 | 
	
		
			
				|  |  | -	name := "qq"
 | 
	
		
			
				|  |  | -	config := &oauth.Config{
 | 
	
		
			
				|  |  | -		ClientId:     "801497180",                        //base.OauthService.GitHub.ClientId, // FIXME: panic when set
 | 
	
		
			
				|  |  | -		ClientSecret: "16cd53b8ad2e16a36fc2c8f87d9388f2", //base.OauthService.GitHub.ClientSecret,
 | 
	
		
			
				|  |  | -		Scope:        "all",
 | 
	
		
			
				|  |  | -		AuthURL:      "https://open.t.qq.com/cgi-bin/oauth2/authorize",
 | 
	
		
			
				|  |  | -		TokenURL:     "https://open.t.qq.com/cgi-bin/oauth2/access_token",
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	qq.reqUrl = "https://open.t.qq.com/api/user/info"
 | 
	
		
			
				|  |  | -	qq.Transport = &oauth.Transport{
 | 
	
		
			
				|  |  | -		Config:    config,
 | 
	
		
			
				|  |  | -		Transport: http.DefaultTransport,
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	SocialMap[name] = qq
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialQQ) SetRedirectUrl(url string) {
 | 
	
		
			
				|  |  | -	s.Transport.Config.RedirectURL = url
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -func (s *SocialQQ) UserInfo(token *oauth.Token, URL *url.URL) (*BasicUserInfo, error) {
 | 
	
		
			
				|  |  | -	var data struct {
 | 
	
		
			
				|  |  | -		Data struct {
 | 
	
		
			
				|  |  | -			Id    string `json:"openid"`
 | 
	
		
			
				|  |  | -			Name  string `json:"name"`
 | 
	
		
			
				|  |  | -			Email string `json:"email"`
 | 
	
		
			
				|  |  | -		} `json:"data"`
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	var err error
 | 
	
		
			
				|  |  | -	// https://open.t.qq.com/api/user/info?
 | 
	
		
			
				|  |  | -	//oauth_consumer_key=APP_KEY&
 | 
	
		
			
				|  |  | -	//access_token=ACCESSTOKEN&openid=openid
 | 
	
		
			
				|  |  | -	//clientip=CLIENTIP&oauth_version=2.a
 | 
	
		
			
				|  |  | -	//scope=all
 | 
	
		
			
				|  |  | -	var urls = url.Values{
 | 
	
		
			
				|  |  | -		"oauth_consumer_key": {s.Transport.Config.ClientId},
 | 
	
		
			
				|  |  | -		"access_token":       {token.AccessToken},
 | 
	
		
			
				|  |  | -		"openid":             URL.Query()["openid"],
 | 
	
		
			
				|  |  | -		"oauth_version":      {"2.a"},
 | 
	
		
			
				|  |  | -		"scope":              {"all"},
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	r, err := http.Get(s.reqUrl + "?" + urls.Encode())
 | 
	
		
			
				|  |  | -	if err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	defer r.Body.Close()
 | 
	
		
			
				|  |  | -	if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
 | 
	
		
			
				|  |  | -		return nil, err
 | 
	
		
			
				|  |  | -	}
 | 
	
		
			
				|  |  | -	return &BasicUserInfo{
 | 
	
		
			
				|  |  | -		Identity: data.Data.Id,
 | 
	
		
			
				|  |  | -		Name:     data.Data.Name,
 | 
	
		
			
				|  |  | -		Email:    data.Data.Email,
 | 
	
		
			
				|  |  | -	}, nil
 | 
	
		
			
				|  |  | -}
 |