diff options
author | skyblue <ssx205@gmail.com> | 2014-04-12 01:01:30 +0800 |
---|---|---|
committer | skyblue <ssx205@gmail.com> | 2014-04-12 01:01:30 +0800 |
commit | dd815ae7b532ceba1f96e6751e231dc351eb19b9 (patch) | |
tree | 3e8383106585e5a990ab5074ff3a2fd87d4239d7 | |
parent | df000245d19ffa3e4f88d252763269bbdd04f8eb (diff) | |
download | gitea-dd815ae7b532ceba1f96e6751e231dc351eb19b9.tar.gz gitea-dd815ae7b532ceba1f96e6751e231dc351eb19b9.zip |
finish github oauth2 support
-rw-r--r-- | models/oauth2.go | 31 | ||||
-rw-r--r-- | routers/user/social.go | 29 | ||||
-rw-r--r-- | routers/user/user.go | 31 | ||||
-rw-r--r-- | templates/user/signin.tmpl | 4 | ||||
-rw-r--r-- | templates/user/signup.tmpl | 17 |
5 files changed, 86 insertions, 26 deletions
diff --git a/models/oauth2.go b/models/oauth2.go index 45728b0d51..e50d4039fd 100644 --- a/models/oauth2.go +++ b/models/oauth2.go @@ -4,7 +4,11 @@ package models -import "errors" +import ( + "errors" + + "github.com/gogits/gogs/modules/log" +) // OT: Oauth2 Type const ( @@ -16,17 +20,23 @@ const ( var ( ErrOauth2RecordNotExists = errors.New("not exists oauth2 record") ErrOauth2NotAssociatedWithUser = errors.New("not associated with user") + ErrOauth2NotExist = errors.New("not exist oauth2") ) type Oauth2 struct { Id int64 - Uid int64 // userId + Uid int64 `xorm:"unique(s)"` // userId User *User `xorm:"-"` - Type int `xorm:"pk unique(oauth)"` // twitter,github,google... - Identity string `xorm:"pk unique(oauth)"` // id.. + Type int `xorm:"unique(s) unique(oauth)"` // twitter,github,google... + Identity string `xorm:"unique(s) unique(oauth)"` // id.. Token string `xorm:"VARCHAR(200) not null"` } +func BindUserOauth2(userId, oauthId int64) error { + _, err := orm.Id(oauthId).Update(&Oauth2{Uid: userId}) + return err +} + func AddOauth2(oa *Oauth2) (err error) { if _, err = orm.Insert(oa); err != nil { return err @@ -47,3 +57,16 @@ func GetOauth2(identity string) (oa *Oauth2, err error) { oa.User, err = GetUserById(oa.Uid) return oa, err } + +func GetOauth2ById(id int64) (oa *Oauth2, err error) { + oa = new(Oauth2) + has, err := orm.Id(id).Get(oa) + log.Info("oa: %v", oa) + if err != nil { + return nil, err + } + if !has { + return nil, ErrOauth2NotExist + } + return oa, nil +} diff --git a/routers/user/social.go b/routers/user/social.go index 2b60ab9ffd..8568bc2af8 100644 --- a/routers/user/social.go +++ b/routers/user/social.go @@ -22,10 +22,9 @@ import ( type SocialConnector interface { Identity() string - Type() int Name() string Email() string - Token() string + TokenString() string } type SocialGithub struct { @@ -34,17 +33,13 @@ type SocialGithub struct { Name string `json:"login"` Email string `json:"email"` } - WebToken *oauth.Token + Token *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 } @@ -53,8 +48,8 @@ func (s *SocialGithub) Email() string { return s.data.Email } -func (s *SocialGithub) Token() string { - data, _ := json.Marshal(s.WebToken) +func (s *SocialGithub) TokenString() string { + data, _ := json.Marshal(s.Token) return string(data) } @@ -62,7 +57,7 @@ func (s *SocialGithub) Token() string { func (s *SocialGithub) Update() error { scope := "https://api.github.com/user" transport := &oauth.Transport{ - Token: s.WebToken, + Token: s.Token, } log.Debug("update github info") r, err := transport.Client().Get(scope) @@ -122,7 +117,7 @@ func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) { next = extractPath(ctx.Query("state")) log.Debug("success token: %v", tk) - gh := &SocialGithub{WebToken: tk} + gh := &SocialGithub{Token: tk} if err = gh.Update(); err != nil { // FIXME: handle error page 501 log.Error("connect with github error: %s", err) @@ -137,9 +132,9 @@ func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) { ctx.Session.Set("userName", oa.User.Name) case models.ErrOauth2RecordNotExists: oa = &models.Oauth2{} - oa.Uid = 0 - oa.Type = soc.Type() - oa.Token = soc.Token() + oa.Uid = -1 + oa.Type = models.OT_GITHUB + oa.Token = soc.TokenString() oa.Identity = soc.Identity() log.Debug("oa: %v", oa) if err = models.AddOauth2(oa); err != nil { @@ -147,7 +142,11 @@ func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) { return } case models.ErrOauth2NotAssociatedWithUser: - // ignore it. judge in /usr/login page + ctx.Session.Set("socialName", soc.Name()) + ctx.Session.Set("socialEmail", soc.Email()) + ctx.Session.Set("socialId", oa.Id) + ctx.Redirect("/user/sign_up") + return default: log.Error(err.Error()) // FIXME: handle error page return diff --git a/routers/user/user.go b/routers/user/user.go index 37c6baa9f2..0d9f67e497 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -82,6 +82,7 @@ func SignIn(ctx *middleware.Context) { ctx.Data["OauthGitHubEnabled"] = base.OauthService.GitHub.Enabled } + var user *models.User // Check auto-login. userName := ctx.GetCookie(base.CookieUserName) if len(userName) == 0 { @@ -90,15 +91,17 @@ func SignIn(ctx *middleware.Context) { } isSucceed := false + var err error defer func() { if !isSucceed { log.Trace("%s auto-login cookie cleared: %s", ctx.Req.RequestURI, userName) ctx.SetCookie(base.CookieUserName, "", -1) ctx.SetCookie(base.CookieRememberName, "", -1) + return } }() - user, err := models.GetUserByName(userName) + user, err = models.GetUserByName(userName) if err != nil { ctx.HTML(200, "user/signin") return @@ -112,6 +115,7 @@ func SignIn(ctx *middleware.Context) { } isSucceed = true + ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 { @@ -155,6 +159,13 @@ func SignInPost(ctx *middleware.Context, form auth.LogInForm) { ctx.SetSecureCookie(secret, base.CookieRememberName, user.Name, days) } + // Bind with social account + if sid, ok := ctx.Session.Get("socialId").(int64); ok { + if err = models.BindUserOauth2(user.Id, sid); err != nil { + log.Error("bind user error: %v", err) + } + ctx.Session.Delete("socialId") + } ctx.Session.Set("userId", user.Id) ctx.Session.Set("userName", user.Name) if redirectTo, _ := url.QueryUnescape(ctx.GetCookie("redirect_to")); len(redirectTo) > 0 { @@ -169,6 +180,7 @@ func SignInPost(ctx *middleware.Context, form auth.LogInForm) { func SignOut(ctx *middleware.Context) { ctx.Session.Delete("userId") ctx.Session.Delete("userName") + ctx.Session.Delete("socialId") ctx.SetCookie(base.CookieUserName, "", -1) ctx.SetCookie(base.CookieRememberName, "", -1) ctx.Redirect("/") @@ -178,11 +190,23 @@ func SignUp(ctx *middleware.Context) { ctx.Data["Title"] = "Sign Up" ctx.Data["PageIsSignUp"] = true + if sid, ok := ctx.Session.Get("socialId").(int64); ok { + var err error + if _, err = models.GetOauth2ById(sid); err == nil { + ctx.Data["IsSocialLogin"] = true + // FIXME: don't set in error page + ctx.Data["username"] = ctx.Session.Get("socialName") + ctx.Data["email"] = ctx.Session.Get("socialEmail") + } else { + log.Error("unaccepted oauth error: %s", err) // FIXME: should it show in page + } + } if base.Service.DisenableRegisteration { ctx.Data["DisenableRegisteration"] = true ctx.HTML(200, "user/signup") return } + log.Info("session: %v", ctx.Session.Get("socialId")) ctx.HTML(200, "user/signup") } @@ -232,6 +256,11 @@ func SignUpPost(ctx *middleware.Context, form auth.RegisterForm) { } log.Trace("%s User created: %s", ctx.Req.RequestURI, strings.ToLower(form.UserName)) + // Bind Social Account + if sid, ok := ctx.Session.Get("socialId").(int64); ok { + models.BindUserOauth2(u.Id, sid) + ctx.Session.Delete("socialId") + } // Send confirmation e-mail. if base.Service.RegisterEmailConfirm && u.Id > 1 { diff --git a/templates/user/signin.tmpl b/templates/user/signin.tmpl index 294c0d3418..a06e3ca8a0 100644 --- a/templates/user/signin.tmpl +++ b/templates/user/signin.tmpl @@ -46,9 +46,9 @@ {{if .OauthEnabled}} <div class="form-group text-center" id="social-login"> <h4>Log In with Social Accounts</h4> - {{if .OauthGitHubEnabled}}<a href="/user/login/github"><i class="fa fa-github-square fa-3x"></i></a>{{end}} + {{if .OauthGitHubEnabled}}<a href="/user/login/github?next=/user/sign_up"><i class="fa fa-github-square fa-3x"></i></a>{{end}} </div> {{end}} </form> </div> -{{template "base/footer" .}}
\ No newline at end of file +{{template "base/footer" .}} diff --git a/templates/user/signup.tmpl b/templates/user/signup.tmpl index 87fa80ccc1..b12333a257 100644 --- a/templates/user/signup.tmpl +++ b/templates/user/signup.tmpl @@ -6,19 +6,24 @@ {{if .DisenableRegisteration}} Sorry, registeration has been disenabled, you can only get account from administrator. {{else}} - <h3>Sign Up</h3> + {{if .IsSocialLogin}} + <h3>Social login: 2nd step <small>complete information</small></h3> + {{else}} + <h3>Sign Up</h3> + {{end}} {{template "base/alert" .}} + {{if .IsSocialLogin}} + {{end}} <div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> <label class="col-md-4 control-label">Username: </label> <div class="col-md-6"> <input name="username" class="form-control" placeholder="Type your username" value="{{.username}}" required="required"> </div> </div> - <div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> <label class="col-md-4 control-label">Email: </label> <div class="col-md-6"> - <input name="email" class="form-control" placeholder="Type your e-mail address" value="{{.email}}" required="required" title="Email is not valid"> + <input name="email" class="form-control" placeholder="Type your e-mail address" value="{{.email}}{{.socialEmail}}" required="required" title="Email is not valid"> </div> </div> @@ -44,10 +49,14 @@ <div class="form-group"> <div class="col-md-offset-4 col-md-6"> + {{if .IsSocialLogin}} + <a href="/user/login">Already have an account? Bind now!</a> + {{else}} <a href="/user/login">Already have an account? Sign in now!</a> + {{end}} </div> </div> {{end}} </form> </div> -{{template "base/footer" .}}
\ No newline at end of file +{{template "base/footer" .}} |