ext_user.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package login
  2. import (
  3. "github.com/grafana/grafana/pkg/bus"
  4. "github.com/grafana/grafana/pkg/log"
  5. m "github.com/grafana/grafana/pkg/models"
  6. "github.com/grafana/grafana/pkg/services/quota"
  7. )
  8. func init() {
  9. bus.AddHandler("auth", UpsertUser)
  10. }
  11. var (
  12. logger = log.New("login.ext_user")
  13. )
  14. func UpsertUser(cmd *m.UpsertUserCommand) error {
  15. extUser := cmd.ExternalUser
  16. userQuery := &m.GetUserByAuthInfoQuery{
  17. AuthModule: extUser.AuthModule,
  18. AuthId: extUser.AuthId,
  19. UserId: extUser.UserId,
  20. Email: extUser.Email,
  21. Login: extUser.Login,
  22. }
  23. err := bus.Dispatch(userQuery)
  24. if err != m.ErrUserNotFound && err != nil {
  25. return err
  26. }
  27. if err != nil {
  28. if !cmd.SignupAllowed {
  29. log.Warn("Not allowing %s login, user not found in internal user database and allow signup = false", extUser.AuthModule)
  30. return ErrInvalidCredentials
  31. }
  32. limitReached, err := quota.QuotaReached(cmd.ReqContext, "user")
  33. if err != nil {
  34. log.Warn("Error getting user quota. error: %v", err)
  35. return ErrGettingUserQuota
  36. }
  37. if limitReached {
  38. return ErrUsersQuotaReached
  39. }
  40. cmd.Result, err = createUser(extUser)
  41. if err != nil {
  42. return err
  43. }
  44. if extUser.AuthModule != "" {
  45. cmd2 := &m.SetAuthInfoCommand{
  46. UserId: cmd.Result.Id,
  47. AuthModule: extUser.AuthModule,
  48. AuthId: extUser.AuthId,
  49. OAuthToken: extUser.OAuthToken,
  50. }
  51. if err := bus.Dispatch(cmd2); err != nil {
  52. return err
  53. }
  54. }
  55. } else {
  56. cmd.Result = userQuery.Result
  57. err = updateUser(cmd.Result, extUser)
  58. if err != nil {
  59. return err
  60. }
  61. // Always persist the latest token at log-in
  62. if extUser.AuthModule != "" && extUser.OAuthToken != nil {
  63. err = updateUserAuth(cmd.Result, extUser)
  64. if err != nil {
  65. return err
  66. }
  67. }
  68. }
  69. err = syncOrgRoles(cmd.Result, extUser)
  70. if err != nil {
  71. return err
  72. }
  73. // Sync isGrafanaAdmin permission
  74. if extUser.IsGrafanaAdmin != nil && *extUser.IsGrafanaAdmin != cmd.Result.IsAdmin {
  75. if err := bus.Dispatch(&m.UpdateUserPermissionsCommand{UserId: cmd.Result.Id, IsGrafanaAdmin: *extUser.IsGrafanaAdmin}); err != nil {
  76. return err
  77. }
  78. }
  79. err = bus.Dispatch(&m.SyncTeamsCommand{
  80. User: cmd.Result,
  81. ExternalUser: extUser,
  82. })
  83. if err == bus.ErrHandlerNotFound {
  84. return nil
  85. }
  86. return err
  87. }
  88. func createUser(extUser *m.ExternalUserInfo) (*m.User, error) {
  89. cmd := &m.CreateUserCommand{
  90. Login: extUser.Login,
  91. Email: extUser.Email,
  92. Name: extUser.Name,
  93. SkipOrgSetup: len(extUser.OrgRoles) > 0,
  94. }
  95. if err := bus.Dispatch(cmd); err != nil {
  96. return nil, err
  97. }
  98. return &cmd.Result, nil
  99. }
  100. func updateUser(user *m.User, extUser *m.ExternalUserInfo) error {
  101. // sync user info
  102. updateCmd := &m.UpdateUserCommand{
  103. UserId: user.Id,
  104. }
  105. needsUpdate := false
  106. if extUser.Login != "" && extUser.Login != user.Login {
  107. updateCmd.Login = extUser.Login
  108. user.Login = extUser.Login
  109. needsUpdate = true
  110. }
  111. if extUser.Email != "" && extUser.Email != user.Email {
  112. updateCmd.Email = extUser.Email
  113. user.Email = extUser.Email
  114. needsUpdate = true
  115. }
  116. if extUser.Name != "" && extUser.Name != user.Name {
  117. updateCmd.Name = extUser.Name
  118. user.Name = extUser.Name
  119. needsUpdate = true
  120. }
  121. if !needsUpdate {
  122. return nil
  123. }
  124. logger.Debug("Syncing user info", "id", user.Id, "update", updateCmd)
  125. return bus.Dispatch(updateCmd)
  126. }
  127. func updateUserAuth(user *m.User, extUser *m.ExternalUserInfo) error {
  128. updateCmd := &m.UpdateAuthInfoCommand{
  129. AuthModule: extUser.AuthModule,
  130. AuthId: extUser.AuthId,
  131. UserId: user.Id,
  132. OAuthToken: extUser.OAuthToken,
  133. }
  134. log.Debug("Updating user_auth info for user_id %d", user.Id)
  135. return bus.Dispatch(updateCmd)
  136. }
  137. func syncOrgRoles(user *m.User, extUser *m.ExternalUserInfo) error {
  138. // don't sync org roles if none are specified
  139. if len(extUser.OrgRoles) == 0 {
  140. return nil
  141. }
  142. orgsQuery := &m.GetUserOrgListQuery{UserId: user.Id}
  143. if err := bus.Dispatch(orgsQuery); err != nil {
  144. return err
  145. }
  146. handledOrgIds := map[int64]bool{}
  147. deleteOrgIds := []int64{}
  148. // update existing org roles
  149. for _, org := range orgsQuery.Result {
  150. handledOrgIds[org.OrgId] = true
  151. if extUser.OrgRoles[org.OrgId] == "" {
  152. deleteOrgIds = append(deleteOrgIds, org.OrgId)
  153. } else if extUser.OrgRoles[org.OrgId] != org.Role {
  154. // update role
  155. cmd := &m.UpdateOrgUserCommand{OrgId: org.OrgId, UserId: user.Id, Role: extUser.OrgRoles[org.OrgId]}
  156. if err := bus.Dispatch(cmd); err != nil {
  157. return err
  158. }
  159. }
  160. }
  161. // add any new org roles
  162. for orgId, orgRole := range extUser.OrgRoles {
  163. if _, exists := handledOrgIds[orgId]; exists {
  164. continue
  165. }
  166. // add role
  167. cmd := &m.AddOrgUserCommand{UserId: user.Id, Role: orgRole, OrgId: orgId}
  168. err := bus.Dispatch(cmd)
  169. if err != nil && err != m.ErrOrgNotFound {
  170. return err
  171. }
  172. }
  173. // delete any removed org roles
  174. for _, orgId := range deleteOrgIds {
  175. cmd := &m.RemoveOrgUserCommand{OrgId: orgId, UserId: user.Id}
  176. if err := bus.Dispatch(cmd); err != nil {
  177. return err
  178. }
  179. }
  180. // update user's default org if needed
  181. if _, ok := extUser.OrgRoles[user.OrgId]; !ok {
  182. for orgId := range extUser.OrgRoles {
  183. user.OrgId = orgId
  184. break
  185. }
  186. return bus.Dispatch(&m.SetUsingOrgCommand{
  187. UserId: user.Id,
  188. OrgId: user.OrgId,
  189. })
  190. }
  191. return nil
  192. }