social.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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. package user
  5. import (
  6. "encoding/json"
  7. "strconv"
  8. "code.google.com/p/goauth2/oauth"
  9. "github.com/gogits/gogs/models"
  10. "github.com/gogits/gogs/modules/log"
  11. "github.com/gogits/gogs/modules/middleware"
  12. "github.com/gogits/gogs/modules/oauth2"
  13. )
  14. type SocialConnector interface {
  15. Identity() string
  16. Type() int
  17. Name() string
  18. Email() string
  19. Token() string
  20. }
  21. type SocialGithub struct {
  22. data struct {
  23. Id int `json:"id"`
  24. Name string `json:"login"`
  25. Email string `json:"email"`
  26. }
  27. WebToken *oauth.Token
  28. }
  29. func (s *SocialGithub) Identity() string {
  30. return strconv.Itoa(s.data.Id)
  31. }
  32. func (s *SocialGithub) Type() int {
  33. return models.OT_GITHUB
  34. }
  35. func (s *SocialGithub) Name() string {
  36. return s.data.Name
  37. }
  38. func (s *SocialGithub) Email() string {
  39. return s.data.Email
  40. }
  41. func (s *SocialGithub) Token() string {
  42. data, _ := json.Marshal(s.WebToken)
  43. return string(data)
  44. }
  45. // Github API refer: https://developer.github.com/v3/users/
  46. func (s *SocialGithub) Update() error {
  47. scope := "https://api.github.com/user"
  48. transport := &oauth.Transport{
  49. Token: s.WebToken,
  50. }
  51. log.Debug("update github info")
  52. r, err := transport.Client().Get(scope)
  53. if err != nil {
  54. return err
  55. }
  56. defer r.Body.Close()
  57. return json.NewDecoder(r.Body).Decode(&s.data)
  58. }
  59. // github && google && ...
  60. func SocialSignIn(ctx *middleware.Context, tokens oauth2.Tokens) {
  61. gh := &SocialGithub{
  62. WebToken: &oauth.Token{
  63. AccessToken: tokens.Access(),
  64. RefreshToken: tokens.Refresh(),
  65. Expiry: tokens.ExpiryTime(),
  66. Extra: tokens.ExtraData(),
  67. },
  68. }
  69. if len(tokens.Access()) == 0 {
  70. log.Error("empty access")
  71. return
  72. }
  73. var err error
  74. if err = gh.Update(); err != nil {
  75. // FIXME: handle error page
  76. log.Error("connect with github error: %s", err)
  77. return
  78. }
  79. var soc SocialConnector = gh
  80. log.Info("login: %s", soc.Name())
  81. oa, err := models.GetOauth2(soc.Identity())
  82. switch err {
  83. case nil:
  84. ctx.Session.Set("userId", oa.User.Id)
  85. ctx.Session.Set("userName", oa.User.Name)
  86. case models.ErrOauth2RecordNotExists:
  87. oa = &models.Oauth2{}
  88. oa.Uid = 0
  89. oa.Type = soc.Type()
  90. oa.Token = soc.Token()
  91. oa.Identity = soc.Identity()
  92. log.Info("oa: %v", oa)
  93. if err = models.AddOauth2(oa); err != nil {
  94. log.Error("add oauth2 %v", err)
  95. return
  96. }
  97. case models.ErrOauth2NotAssociatedWithUser:
  98. // pass
  99. default:
  100. log.Error(err) // FIXME: handle error page
  101. return
  102. }
  103. ctx.Session.Set("socialId", oa.Id)
  104. log.Info("socialId: %v", oa.Id)
  105. ctx.Redirect("/")
  106. }