Skip to content

Commit d60f7b8

Browse files
committed
Merge branch 'dev' of github.com:gogits/gogs into dev
2 parents 47f3dd4 + 75d2aff commit d60f7b8

File tree

6 files changed

+280
-94
lines changed

6 files changed

+280
-94
lines changed

models/oauth2.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const (
1313
OT_GITHUB = iota + 1
1414
OT_GOOGLE
1515
OT_TWITTER
16+
OT_QQ
1617
)
1718

1819
var (
@@ -26,7 +27,7 @@ type Oauth2 struct {
2627
User *User `xorm:"-"`
2728
Type int `xorm:"unique(s) unique(oauth)"` // twitter,github,google...
2829
Identity string `xorm:"unique(s) unique(oauth)"` // id..
29-
Token string `xorm:"VARCHAR(200) not null"`
30+
Token string `xorm:"TEXT not null"`
3031
}
3132

3233
func BindUserOauth2(userId, oauthId int64) error {
@@ -48,7 +49,7 @@ func GetOauth2(identity string) (oa *Oauth2, err error) {
4849
return
4950
} else if !isExist {
5051
return nil, ErrOauth2RecordNotExists
51-
} else if oa.Uid == 0 {
52+
} else if oa.Uid == -1 {
5253
return oa, ErrOauth2NotAssociatedWithUser
5354
}
5455
oa.User, err = GetUserById(oa.Uid)

routers/user/social.go

Lines changed: 49 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6,65 +6,32 @@ package user
66

77
import (
88
"encoding/json"
9-
"net/http"
9+
"fmt"
1010
"net/url"
11-
"strconv"
1211
"strings"
1312

1413
"code.google.com/p/goauth2/oauth"
1514

15+
"github.com/go-martini/martini"
1616
"github.com/gogits/gogs/models"
1717
"github.com/gogits/gogs/modules/base"
1818
"github.com/gogits/gogs/modules/log"
1919
"github.com/gogits/gogs/modules/middleware"
2020
)
2121

22-
type SocialConnector interface {
23-
Identity() string
24-
Name() string
25-
Email() string
26-
TokenString() string
27-
}
28-
29-
type SocialGithub struct {
30-
data struct {
31-
Id int `json:"id"`
32-
Name string `json:"login"`
33-
Email string `json:"email"`
34-
}
35-
Token *oauth.Token
22+
type BasicUserInfo struct {
23+
Identity string
24+
Name string
25+
Email string
3626
}
3727

38-
func (s *SocialGithub) Identity() string {
39-
return strconv.Itoa(s.data.Id)
40-
}
41-
42-
func (s *SocialGithub) Name() string {
43-
return s.data.Name
44-
}
45-
46-
func (s *SocialGithub) Email() string {
47-
return s.data.Email
48-
}
49-
50-
func (s *SocialGithub) TokenString() string {
51-
data, _ := json.Marshal(s.Token)
52-
return string(data)
53-
}
28+
type SocialConnector interface {
29+
Type() int
30+
SetRedirectUrl(string)
31+
UserInfo(*oauth.Token, *url.URL) (*BasicUserInfo, error)
5432

55-
// Github API refer: https://developer.github.com/v3/users/
56-
func (s *SocialGithub) Update() error {
57-
scope := "https://api.github.com/user"
58-
transport := &oauth.Transport{
59-
Token: s.Token,
60-
}
61-
log.Debug("update github info")
62-
r, err := transport.Client().Get(scope)
63-
if err != nil {
64-
return err
65-
}
66-
defer r.Body.Close()
67-
return json.NewDecoder(r.Body).Decode(&s.data)
33+
AuthCodeURL(string) string
34+
Exchange(string) (*oauth.Token, error)
6835
}
6936

7037
func extractPath(next string) string {
@@ -75,85 +42,76 @@ func extractPath(next string) string {
7542
return n.Path
7643
}
7744

78-
// github && google && ...
79-
func SocialSignIn(ctx *middleware.Context) {
80-
//if base.OauthService != nil && base.OauthService.GitHub.Enabled {
81-
//}
45+
var (
46+
SocialBaseUrl = "/user/login"
47+
SocialMap = make(map[string]SocialConnector)
48+
)
8249

83-
var socid int64
84-
var ok bool
85-
next := extractPath(ctx.Query("next"))
86-
log.Debug("social signed check %s", next)
87-
if socid, ok = ctx.Session.Get("socialId").(int64); ok && socid != 0 {
88-
// already login
89-
ctx.Redirect(next)
90-
log.Info("login soc id: %v", socid)
50+
// github && google && ...
51+
func SocialSignIn(params martini.Params, ctx *middleware.Context) {
52+
if base.OauthService == nil || !base.OauthService.GitHub.Enabled {
53+
ctx.Handle(404, "social login not enabled", nil)
9154
return
9255
}
93-
94-
config := &oauth.Config{
95-
ClientId: base.OauthService.GitHub.ClientId,
96-
ClientSecret: base.OauthService.GitHub.ClientSecret,
97-
RedirectURL: strings.TrimSuffix(base.AppUrl, "/") + ctx.Req.URL.RequestURI(),
98-
Scope: base.OauthService.GitHub.Scopes,
99-
AuthURL: "https://github.com/login/oauth/authorize",
100-
TokenURL: "https://github.com/login/oauth/access_token",
101-
}
102-
transport := &oauth.Transport{
103-
Config: config,
104-
Transport: http.DefaultTransport,
56+
next := extractPath(ctx.Query("next"))
57+
name := params["name"]
58+
connect, ok := SocialMap[name]
59+
if !ok {
60+
ctx.Handle(404, "social login", nil)
61+
return
10562
}
10663
code := ctx.Query("code")
10764
if code == "" {
10865
// redirect to social login page
109-
ctx.Redirect(config.AuthCodeURL(next))
66+
connect.SetRedirectUrl(strings.TrimSuffix(base.AppUrl, "/") + ctx.Req.URL.Host + ctx.Req.URL.Path)
67+
ctx.Redirect(connect.AuthCodeURL(next))
11068
return
11169
}
11270

11371
// handle call back
114-
tk, err := transport.Exchange(code)
72+
tk, err := connect.Exchange(code) // exchange for token
11573
if err != nil {
11674
log.Error("oauth2 handle callback error: %v", err)
117-
return // FIXME, need error page 501
75+
ctx.Handle(500, "exchange code error", nil)
76+
return
11877
}
11978
next = extractPath(ctx.Query("state"))
120-
log.Debug("success token: %v", tk)
79+
log.Trace("success get token")
12180

122-
gh := &SocialGithub{Token: tk}
123-
if err = gh.Update(); err != nil {
124-
// FIXME: handle error page 501
125-
log.Error("connect with github error: %s", err)
81+
ui, err := connect.UserInfo(tk, ctx.Req.URL)
82+
if err != nil {
83+
ctx.Handle(500, fmt.Sprintf("get infomation from %s error: %v", name, err), nil)
84+
log.Error("social connect error: %s", err)
12685
return
12786
}
128-
var soc SocialConnector = gh
129-
log.Info("login: %s", soc.Name())
130-
oa, err := models.GetOauth2(soc.Identity())
87+
log.Info("social login: %s", ui)
88+
oa, err := models.GetOauth2(ui.Identity)
13189
switch err {
13290
case nil:
13391
ctx.Session.Set("userId", oa.User.Id)
13492
ctx.Session.Set("userName", oa.User.Name)
13593
case models.ErrOauth2RecordNotExists:
13694
oa = &models.Oauth2{}
95+
raw, _ := json.Marshal(tk) // json encode
96+
oa.Token = string(raw)
13797
oa.Uid = -1
138-
oa.Type = models.OT_GITHUB
139-
oa.Token = soc.TokenString()
140-
oa.Identity = soc.Identity()
141-
log.Debug("oa: %v", oa)
98+
oa.Type = connect.Type()
99+
oa.Identity = ui.Identity
100+
log.Trace("oa: %v", oa)
142101
if err = models.AddOauth2(oa); err != nil {
143102
log.Error("add oauth2 %v", err) // 501
144103
return
145104
}
146105
case models.ErrOauth2NotAssociatedWithUser:
147-
ctx.Session.Set("socialId", oa.Id)
148-
ctx.Session.Set("socialName", soc.Name())
149-
ctx.Session.Set("socialEmail", soc.Email())
150-
ctx.Redirect("/user/sign_up")
151-
return
106+
next = "/user/sign_up"
152107
default:
153-
log.Error(err.Error()) // FIXME: handle error page
108+
log.Error("other error: %v", err)
109+
ctx.Handle(500, err.Error(), nil)
154110
return
155111
}
156112
ctx.Session.Set("socialId", oa.Id)
157-
log.Debug("socialId: %v", oa.Id)
113+
ctx.Session.Set("socialName", ui.Name)
114+
ctx.Session.Set("socialEmail", ui.Email)
115+
log.Trace("socialId: %v", oa.Id)
158116
ctx.Redirect(next)
159117
}

routers/user/social_github.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2014 The Gogs Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package user
6+
7+
import (
8+
"encoding/json"
9+
"net/http"
10+
"net/url"
11+
"strconv"
12+
"strings"
13+
14+
"code.google.com/p/goauth2/oauth"
15+
"github.com/gogits/gogs/models"
16+
"github.com/gogits/gogs/modules/base"
17+
)
18+
19+
type SocialGithub struct {
20+
Token *oauth.Token
21+
*oauth.Transport
22+
}
23+
24+
func (s *SocialGithub) Type() int {
25+
return models.OT_GITHUB
26+
}
27+
28+
func init() {
29+
github := &SocialGithub{}
30+
name := "github"
31+
config := &oauth.Config{
32+
ClientId: "09383403ff2dc16daaa1", //base.OauthService.GitHub.ClientId, // FIXME: panic when set
33+
ClientSecret: "0e4aa0c3630df396cdcea01a9d45cacf79925fea", //base.OauthService.GitHub.ClientSecret,
34+
RedirectURL: strings.TrimSuffix(base.AppUrl, "/") + "/user/login/" + name, //ctx.Req.URL.RequestURI(),
35+
Scope: "https://api.github.com/user",
36+
AuthURL: "https://github.com/login/oauth/authorize",
37+
TokenURL: "https://github.com/login/oauth/access_token",
38+
}
39+
github.Transport = &oauth.Transport{
40+
Config: config,
41+
Transport: http.DefaultTransport,
42+
}
43+
SocialMap[name] = github
44+
}
45+
46+
func (s *SocialGithub) SetRedirectUrl(url string) {
47+
s.Transport.Config.RedirectURL = url
48+
}
49+
50+
func (s *SocialGithub) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
51+
transport := &oauth.Transport{
52+
Token: token,
53+
}
54+
var data struct {
55+
Id int `json:"id"`
56+
Name string `json:"login"`
57+
Email string `json:"email"`
58+
}
59+
var err error
60+
r, err := transport.Client().Get(s.Transport.Scope)
61+
if err != nil {
62+
return nil, err
63+
}
64+
defer r.Body.Close()
65+
if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
66+
return nil, err
67+
}
68+
return &BasicUserInfo{
69+
Identity: strconv.Itoa(data.Id),
70+
Name: data.Name,
71+
Email: data.Email,
72+
}, nil
73+
}

routers/user/social_google.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright 2014 The Gogs Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package user
6+
7+
import (
8+
"encoding/json"
9+
"net/http"
10+
"net/url"
11+
"github.com/gogits/gogs/models"
12+
13+
"code.google.com/p/goauth2/oauth"
14+
)
15+
16+
type SocialGoogle struct {
17+
Token *oauth.Token
18+
*oauth.Transport
19+
}
20+
21+
func (s *SocialGoogle) Type() int {
22+
return models.OT_GOOGLE
23+
}
24+
25+
func init() {
26+
google := &SocialGoogle{}
27+
name := "google"
28+
// get client id and secret from
29+
// https://console.developers.google.com/project
30+
config := &oauth.Config{
31+
ClientId: "849753812404-mpd7ilvlb8c7213qn6bre6p6djjskti9.apps.googleusercontent.com", //base.OauthService.GitHub.ClientId, // FIXME: panic when set
32+
ClientSecret: "VukKc4MwaJUSmiyv3D7ANVCa", //base.OauthService.GitHub.ClientSecret,
33+
Scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
34+
AuthURL: "https://accounts.google.com/o/oauth2/auth",
35+
TokenURL: "https://accounts.google.com/o/oauth2/token",
36+
}
37+
google.Transport = &oauth.Transport{
38+
Config: config,
39+
Transport: http.DefaultTransport,
40+
}
41+
SocialMap[name] = google
42+
}
43+
44+
func (s *SocialGoogle) SetRedirectUrl(url string) {
45+
s.Transport.Config.RedirectURL = url
46+
}
47+
48+
func (s *SocialGoogle) UserInfo(token *oauth.Token, _ *url.URL) (*BasicUserInfo, error) {
49+
transport := &oauth.Transport{Token: token}
50+
var data struct {
51+
Id string `json:"id"`
52+
Name string `json:"name"`
53+
Email string `json:"email"`
54+
}
55+
var err error
56+
57+
reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
58+
r, err := transport.Client().Get(reqUrl)
59+
if err != nil {
60+
return nil, err
61+
}
62+
defer r.Body.Close()
63+
if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
64+
return nil, err
65+
}
66+
return &BasicUserInfo{
67+
Identity: data.Id,
68+
Name: data.Name,
69+
Email: data.Email,
70+
}, nil
71+
}

0 commit comments

Comments
 (0)