org_invite.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package api
  2. import (
  3. "fmt"
  4. "github.com/grafana/grafana/pkg/api/dtos"
  5. "github.com/grafana/grafana/pkg/bus"
  6. "github.com/grafana/grafana/pkg/events"
  7. "github.com/grafana/grafana/pkg/metrics"
  8. "github.com/grafana/grafana/pkg/middleware"
  9. m "github.com/grafana/grafana/pkg/models"
  10. "github.com/grafana/grafana/pkg/setting"
  11. "github.com/grafana/grafana/pkg/util"
  12. )
  13. func GetPendingOrgInvites(c *middleware.Context) Response {
  14. query := m.GetTempUsersForOrgQuery{OrgId: c.OrgId, Status: m.TmpUserInvitePending}
  15. if err := bus.Dispatch(&query); err != nil {
  16. return ApiError(500, "Failed to get invites from db", err)
  17. }
  18. for _, invite := range query.Result {
  19. invite.Url = setting.ToAbsUrl("invite/" + invite.Code)
  20. }
  21. return Json(200, query.Result)
  22. }
  23. func AddOrgInvite(c *middleware.Context, inviteDto dtos.AddInviteForm) Response {
  24. if !inviteDto.Role.IsValid() {
  25. return ApiError(400, "Invalid role specified", nil)
  26. }
  27. if !util.IsEmail(inviteDto.Email) {
  28. return ApiError(400, "Invalid email specified", nil)
  29. }
  30. // first try get existing user
  31. userQuery := m.GetUserByLoginQuery{LoginOrEmail: inviteDto.Email}
  32. if err := bus.Dispatch(&userQuery); err != nil {
  33. if err != m.ErrUserNotFound {
  34. return ApiError(500, "Failed to query db for existing user check", err)
  35. }
  36. } else {
  37. // user exists, add org role
  38. createOrgUserCmd := m.AddOrgUserCommand{OrgId: c.OrgId, UserId: userQuery.Result.Id, Role: inviteDto.Role}
  39. if err := bus.Dispatch(&createOrgUserCmd); err != nil {
  40. if err == m.ErrOrgUserAlreadyAdded {
  41. return ApiError(412, fmt.Sprintf("User %s is already added to organization", inviteDto.Email), err)
  42. }
  43. return ApiError(500, "Error while trying to create org user", err)
  44. } else {
  45. return ApiSuccess("Existing Grafana user added to org " + c.OrgName)
  46. }
  47. }
  48. cmd := m.CreateTempUserCommand{}
  49. cmd.OrgId = c.OrgId
  50. cmd.Email = inviteDto.Email
  51. cmd.Name = inviteDto.Name
  52. cmd.Status = m.TmpUserInvitePending
  53. cmd.InvitedByUserId = c.UserId
  54. cmd.Code = util.GetRandomString(30)
  55. cmd.Role = inviteDto.Role
  56. cmd.RemoteAddr = c.Req.RemoteAddr
  57. if err := bus.Dispatch(&cmd); err != nil {
  58. return ApiError(500, "Failed to save invite to database", err)
  59. }
  60. // send invite email
  61. if !inviteDto.SkipEmails {
  62. emailCmd := m.SendEmailCommand{
  63. To: []string{inviteDto.Email},
  64. Template: "new_user_invite.html",
  65. Data: map[string]interface{}{
  66. "NameOrEmail": util.StringsFallback2(cmd.Name, cmd.Email),
  67. "OrgName": c.OrgName,
  68. "Email": c.Email,
  69. "LinkUrl": setting.ToAbsUrl("signup/invited/" + cmd.Code),
  70. "InvitedBy": util.StringsFallback2(c.Name, c.Email),
  71. },
  72. }
  73. if err := bus.Dispatch(&emailCmd); err != nil {
  74. return ApiError(500, "Failed to send email invite", err)
  75. }
  76. return ApiSuccess(fmt.Sprintf("Sent invite to %s", inviteDto.Email))
  77. }
  78. return ApiSuccess(fmt.Sprintf("Created invite for %s", inviteDto.Email))
  79. }
  80. func RevokeInvite(c *middleware.Context) Response {
  81. cmd := m.UpdateTempUserStatusCommand{
  82. Code: c.Params(":code"),
  83. Status: m.TmpUserRevoked,
  84. }
  85. if err := bus.Dispatch(&cmd); err != nil {
  86. return ApiError(500, "Failed to update invite status", err)
  87. }
  88. return ApiSuccess("Invite revoked")
  89. }
  90. func GetInviteInfoByCode(c *middleware.Context) Response {
  91. query := m.GetTempUserByCodeQuery{Code: c.Params(":code")}
  92. if err := bus.Dispatch(&query); err != nil {
  93. if err == m.ErrTempUserNotFound {
  94. return ApiError(404, "Invite not found", nil)
  95. }
  96. return ApiError(500, "Failed to get invite", err)
  97. }
  98. info := dtos.InviteInfo{
  99. Email: query.Result.Email,
  100. Name: query.Result.Name,
  101. Username: query.Result.Email,
  102. }
  103. return Json(200, &info)
  104. }
  105. func CompleteInvite(c *middleware.Context, completeInvite dtos.CompleteInviteForm) Response {
  106. query := m.GetTempUserByCodeQuery{Code: completeInvite.InviteCode}
  107. if err := bus.Dispatch(&query); err != nil {
  108. if err == m.ErrTempUserNotFound {
  109. return ApiError(404, "Invite not found", nil)
  110. }
  111. return ApiError(500, "Failed to get invite", err)
  112. }
  113. invite := query.Result
  114. if invite.Status != m.TmpUserInvitePending {
  115. return ApiError(412, fmt.Sprintf("Invite cannot be used in status %s", invite.Status), nil)
  116. }
  117. cmd := m.CreateUserCommand{
  118. Email: completeInvite.Email,
  119. Name: completeInvite.Name,
  120. Login: completeInvite.Username,
  121. Password: completeInvite.Password,
  122. }
  123. if err := bus.Dispatch(&cmd); err != nil {
  124. return ApiError(500, "failed to create user", err)
  125. }
  126. user := cmd.Result
  127. bus.Publish(&events.UserSignedUp{
  128. Id: user.Id,
  129. Name: user.Name,
  130. Email: user.Email,
  131. Login: user.Login,
  132. })
  133. // update temp user status
  134. updateTmpUserCmd := m.UpdateTempUserStatusCommand{Code: invite.Code, Status: m.TmpUserCompleted}
  135. if err := bus.Dispatch(&updateTmpUserCmd); err != nil {
  136. return ApiError(500, "Failed to update invite status", err)
  137. }
  138. loginUserWithUser(&user, c)
  139. metrics.M_Api_User_SignUp.Inc(1)
  140. metrics.M_Api_User_SignUpInvite.Inc(1)
  141. return ApiSuccess("User created and logged in")
  142. }