Просмотр исходного кода

first works oauth2(github). need to login with /user/login/github

skyblue 11 лет назад
Родитель
Сommit
05fb34eacd
3 измененных файлов с 125 добавлено и 31 удалено
  1. 27 6
      models/oauth2.go
  2. 92 23
      routers/user/social.go
  3. 6 2
      web.go

+ 27 - 6
models/oauth2.go

@@ -1,6 +1,6 @@
 package models
 
-import "time"
+import "fmt"
 
 // OT: Oauth2 Type
 const (
@@ -10,9 +10,30 @@ const (
 )
 
 type Oauth2 struct {
-	Uid         int64     `xorm:"pk"`               // userId
-	Type        int       `xorm:"pk unique(oauth)"` // twitter,github,google...
-	Identity    string    `xorm:"pk unique(oauth)"` // id..
-	Token       string    `xorm:"VARCHAR(200) not null"`
-	RefreshTime time.Time `xorm:"created"`
+	Uid      int64  `xorm:"pk"`               // userId
+	Type     int    `xorm:"pk unique(oauth)"` // twitter,github,google...
+	Identity string `xorm:"pk unique(oauth)"` // id..
+	Token    string `xorm:"VARCHAR(200) not null"`
+	//RefreshTime time.Time `xorm:"created"`
+}
+
+func AddOauth2(oa *Oauth2) (err error) {
+	if _, err = orm.Insert(oa); err != nil {
+		return err
+	}
+	return nil
+}
+
+func GetOauth2User(identity string) (u *User, err error) {
+	oa := &Oauth2{}
+	oa.Identity = identity
+	exists, err := orm.Get(oa)
+	if err != nil {
+		return
+	}
+	if !exists {
+		err = fmt.Errorf("not exists oauth2: %s", identity)
+		return
+	}
+	return GetUserById(oa.Uid)
 }

+ 92 - 23
routers/user/social.go

@@ -5,45 +5,114 @@ package user
 
 import (
 	"encoding/json"
+	"strconv"
 
-	"code.google.com/p/goauth2/oauth"
+	"github.com/gogits/gogs/models"
+	"github.com/gogits/gogs/modules/base"
 	"github.com/gogits/gogs/modules/log"
-	"github.com/gogits/gogs/modules/oauth2"
+	"github.com/gogits/gogs/modules/middleware"
+	//"github.com/gogits/gogs/modules/oauth2"
+
+	"code.google.com/p/goauth2/oauth"
+	"github.com/martini-contrib/oauth2"
 )
 
-// github && google && ...
-func SocialSignIn(tokens oauth2.Tokens) {
-	transport := &oauth.Transport{}
-	transport.Token = &oauth.Token{
-		AccessToken:  tokens.Access(),
-		RefreshToken: tokens.Refresh(),
-		Expiry:       tokens.ExpiryTime(),
-		Extra:        tokens.ExtraData(),
-	}
+type SocialConnector interface {
+	Identity() string
+	Type() int
+	Name() string
+	Email() string
+	Token() string
+}
 
-	// Github API refer: https://developer.github.com/v3/users/
-	// FIXME: need to judge url
-	type GithubUser struct {
+type SocialGithub struct {
+	data struct {
 		Id    int    `json:"id"`
 		Name  string `json:"login"`
 		Email string `json:"email"`
 	}
+	WebToken *oauth.Token
+}
+
+func (s *SocialGithub) Identity() string {
+	return strconv.Itoa(s.data.Id)
+}
+
+func (s *SocialGithub) Type() int {
+	return models.OT_GITHUB
+}
+
+func (s *SocialGithub) Name() string {
+	return s.data.Name
+}
+
+func (s *SocialGithub) Email() string {
+	return s.data.Email
+}
 
-	// Make the request.
+func (s *SocialGithub) Token() string {
+	data, _ := json.Marshal(s.WebToken)
+	return string(data)
+}
+
+// Github API refer: https://developer.github.com/v3/users/
+func (s *SocialGithub) Update() error {
 	scope := "https://api.github.com/user"
+	transport := &oauth.Transport{
+		Token: s.WebToken,
+	}
+	log.Debug("update github info")
 	r, err := transport.Client().Get(scope)
 	if err != nil {
-		log.Error("connect with github error: %s", err)
-		// FIXME: handle error page
-		return
+		return err
 	}
 	defer r.Body.Close()
+	return json.NewDecoder(r.Body).Decode(&s.data)
+}
 
-	user := &GithubUser{}
-	err = json.NewDecoder(r.Body).Decode(user)
-	if err != nil {
-		log.Error("Get: %s", err)
+// github && google && ...
+func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) {
+	gh := &SocialGithub{
+		WebToken: &oauth.Token{
+			AccessToken:  tokens.Access(),
+			RefreshToken: tokens.Refresh(),
+			Expiry:       tokens.ExpiryTime(),
+			Extra:        tokens.ExtraData(),
+		},
 	}
-	log.Info("login: %s", user.Name)
+	var err error
+	var u *models.User
+	if err = gh.Update(); err != nil {
+		// FIXME: handle error page
+		log.Error("connect with github error: %s", err)
+		return
+	}
+	var soc SocialConnector = gh
+	log.Info("login: %s", soc.Name())
 	// FIXME: login here, user email to check auth, if not registe, then generate a uniq username
+	if u, err = models.GetOauth2User(soc.Identity()); err != nil {
+		u = &models.User{
+			Name:     soc.Name(),
+			Email:    soc.Email(),
+			Passwd:   "123456",
+			IsActive: !base.Service.RegisterEmailConfirm,
+		}
+		if u, err = models.RegisterUser(u); err != nil {
+			log.Error("register user: %v", err)
+			return
+		}
+		oa := &models.Oauth2{}
+		oa.Uid = u.Id
+		oa.Type = soc.Type()
+		oa.Token = soc.Token()
+		oa.Identity = soc.Identity()
+		log.Info("oa: %v", oa)
+		if err = models.AddOauth2(oa); err != nil {
+			log.Error("add oauth2 %v", err)
+			return
+		}
+	}
+	ctx.Session.Set("userId", u.Id)
+	ctx.Session.Set("userName", u.Name)
+	ctx.Redirect("/")
 }

+ 6 - 2
web.go

@@ -20,13 +20,16 @@ import (
 	"github.com/gogits/gogs/modules/base"
 	"github.com/gogits/gogs/modules/log"
 	"github.com/gogits/gogs/modules/middleware"
-	"github.com/gogits/gogs/modules/oauth2"
+	//"github.com/gogits/gogs/modules/oauth2"
 	"github.com/gogits/gogs/routers"
 	"github.com/gogits/gogs/routers/admin"
 	"github.com/gogits/gogs/routers/api/v1"
 	"github.com/gogits/gogs/routers/dev"
 	"github.com/gogits/gogs/routers/repo"
 	"github.com/gogits/gogs/routers/user"
+
+	"github.com/martini-contrib/oauth2"
+	"github.com/martini-contrib/sessions"
 )
 
 var CmdWeb = cli.Command{
@@ -61,6 +64,7 @@ func runWeb(*cli.Context) {
 
 	scope := "https://api.github.com/user"
 	oauth2.PathCallback = "/oauth2callback"
+	m.Use(sessions.Sessions("my_session", sessions.NewCookieStore([]byte("secret123"))))
 	m.Use(oauth2.Github(&oauth2.Options{
 		ClientId:     "09383403ff2dc16daaa1",
 		ClientSecret: "5f6e7101d30b77952aab22b75eadae17551ea6b5",
@@ -88,7 +92,7 @@ func runWeb(*cli.Context) {
 	m.Get("/avatar/:hash", avt.ServeHTTP)
 
 	m.Group("/user", func(r martini.Router) {
-		r.Any("/login/github", user.SocialSignIn)
+		r.Any("/login/github", reqSignOut, oauth2.LoginRequired, user.SocialSignIn)
 		r.Any("/login", binding.BindIgnErr(auth.LogInForm{}), user.SignIn)
 		r.Any("/sign_up", binding.BindIgnErr(auth.RegisterForm{}), user.SignUp)
 		r.Any("/forget_password", user.ForgotPasswd)