From 05fb34eacdbec59fb8bcdf96c82c0855e6ec78d2 Mon Sep 17 00:00:00 2001 From: skyblue Date: Mon, 7 Apr 2014 18:01:25 +0800 Subject: [PATCH] first works oauth2(github). need to login with /user/login/github --- models/oauth2.go | 33 +++++++++--- routers/user/social.go | 115 ++++++++++++++++++++++++++++++++--------- web.go | 8 ++- 3 files changed, 125 insertions(+), 31 deletions(-) diff --git a/models/oauth2.go b/models/oauth2.go index 70dcd5100..a17d4e30f 100644 --- a/models/oauth2.go +++ b/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) } diff --git a/routers/user/social.go b/routers/user/social.go index b59f49630..f5577d809 100644 --- a/routers/user/social.go +++ b/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("/") } diff --git a/web.go b/web.go index 86c395e7b..c8fb8dc09 100644 --- a/web.go +++ b/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)