social.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package social
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "strings"
  7. "github.com/gogits/gogs/models"
  8. "github.com/golang/oauth2"
  9. "github.com/torkelo/grafana-pro/pkg/log"
  10. "github.com/torkelo/grafana-pro/pkg/setting"
  11. )
  12. type BasicUserInfo struct {
  13. Identity string
  14. Name string
  15. Email string
  16. Login string
  17. Company string
  18. }
  19. type SocialConnector interface {
  20. Type() int
  21. UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error)
  22. AuthCodeURL(state, accessType, prompt string) string
  23. NewTransportWithCode(code string) (*oauth2.Transport, error)
  24. }
  25. var (
  26. SocialBaseUrl = "/login/"
  27. SocialMap = make(map[string]SocialConnector)
  28. )
  29. func NewOAuthService() {
  30. if !setting.Cfg.MustBool("oauth", "enabled") {
  31. return
  32. }
  33. setting.OAuthService = &setting.OAuther{}
  34. setting.OAuthService.OAuthInfos = make(map[string]*setting.OAuthInfo)
  35. allOauthes := []string{"github", "google", "twitter"}
  36. // Load all OAuth config data.
  37. for _, name := range allOauthes {
  38. info := &setting.OAuthInfo{
  39. ClientId: setting.Cfg.MustValue("oauth."+name, "client_id"),
  40. ClientSecret: setting.Cfg.MustValue("oauth."+name, "client_secret"),
  41. Scopes: setting.Cfg.MustValueArray("oauth."+name, "scopes", " "),
  42. AuthUrl: setting.Cfg.MustValue("oauth."+name, "auth_url"),
  43. TokenUrl: setting.Cfg.MustValue("oauth."+name, "token_url"),
  44. Enabled: setting.Cfg.MustBool("oauth."+name, "enabled"),
  45. }
  46. if !info.Enabled {
  47. continue
  48. }
  49. opts := &oauth2.Options{
  50. ClientID: info.ClientId,
  51. ClientSecret: info.ClientSecret,
  52. RedirectURL: strings.TrimSuffix(setting.AppUrl, "/") + SocialBaseUrl + name,
  53. Scopes: info.Scopes,
  54. }
  55. setting.OAuthService.OAuthInfos[name] = info
  56. config, err := oauth2.NewConfig(opts, info.AuthUrl, info.TokenUrl)
  57. if err != nil {
  58. log.Error(3, "Failed to init oauth service", err)
  59. continue
  60. }
  61. // GitHub.
  62. if name == "github" {
  63. setting.OAuthService.GitHub = true
  64. SocialMap["github"] = &SocialGithub{Config: config}
  65. }
  66. // Google.
  67. if name == "google" {
  68. setting.OAuthService.Google = true
  69. SocialMap["google"] = &SocialGoogle{Config: config}
  70. }
  71. }
  72. }
  73. type SocialGithub struct {
  74. *oauth2.Config
  75. }
  76. func (s *SocialGithub) Type() int {
  77. return int(models.GITHUB)
  78. }
  79. func (s *SocialGithub) UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error) {
  80. var data struct {
  81. Id int `json:"id"`
  82. Name string `json:"login"`
  83. Email string `json:"email"`
  84. }
  85. var err error
  86. client := http.Client{Transport: transport}
  87. r, err := client.Get("https://api.github.com/user")
  88. if err != nil {
  89. return nil, err
  90. }
  91. defer r.Body.Close()
  92. if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
  93. return nil, err
  94. }
  95. return &BasicUserInfo{
  96. Identity: strconv.Itoa(data.Id),
  97. Name: data.Name,
  98. Email: data.Email,
  99. }, nil
  100. }
  101. // ________ .__
  102. // / _____/ ____ ____ ____ | | ____
  103. // / \ ___ / _ \ / _ \ / ___\| | _/ __ \
  104. // \ \_\ ( <_> | <_> ) /_/ > |_\ ___/
  105. // \______ /\____/ \____/\___ /|____/\___ >
  106. // \/ /_____/ \/
  107. type SocialGoogle struct {
  108. *oauth2.Config
  109. }
  110. func (s *SocialGoogle) Type() int {
  111. return int(models.GOOGLE)
  112. }
  113. func (s *SocialGoogle) UserInfo(transport *oauth2.Transport) (*BasicUserInfo, error) {
  114. var data struct {
  115. Id string `json:"id"`
  116. Name string `json:"name"`
  117. Email string `json:"email"`
  118. }
  119. var err error
  120. reqUrl := "https://www.googleapis.com/oauth2/v1/userinfo"
  121. client := http.Client{Transport: transport}
  122. r, err := client.Get(reqUrl)
  123. if err != nil {
  124. return nil, err
  125. }
  126. defer r.Body.Close()
  127. if err = json.NewDecoder(r.Body).Decode(&data); err != nil {
  128. return nil, err
  129. }
  130. return &BasicUserInfo{
  131. Identity: data.Id,
  132. Name: data.Name,
  133. Email: data.Email,
  134. }, nil
  135. }