login.go 5.8 KB

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