diff --git a/pkg/api/org_invite.go b/pkg/api/org_invite.go index e3812e726e80bc6..3974faeaeefef43 100644 --- a/pkg/api/org_invite.go +++ b/pkg/api/org_invite.go @@ -1,6 +1,8 @@ package api import ( + "fmt" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/events" @@ -43,6 +45,9 @@ func AddOrgInvite(c *middleware.Context, inviteDto dtos.AddInviteForm) Response // user exists, add org role createOrgUserCmd := m.AddOrgUserCommand{OrgId: c.OrgId, UserId: userQuery.Result.Id, Role: inviteDto.Role} if err := bus.Dispatch(&createOrgUserCmd); err != nil { + if err == m.ErrOrgUserAlreadyAdded { + return ApiError(412, fmt.Sprintf("User %s is already added to organization", inviteDto.Email), err) + } return ApiError(500, "Error while trying to create org user", err) } else { return ApiSuccess("Existing Grafana user added to org " + c.OrgName) @@ -80,9 +85,10 @@ func AddOrgInvite(c *middleware.Context, inviteDto dtos.AddInviteForm) Response if err := bus.Dispatch(&emailCmd); err != nil { return ApiError(500, "Failed to send email invite", err) } + return ApiSuccess(fmt.Sprintf("Sent invite to %s", inviteDto.Email)) } - return ApiSuccess("ok, done!") + return ApiSuccess(fmt.Sprintf("Created invite for %s", inviteDto.Email)) } func RevokeInvite(c *middleware.Context) Response { diff --git a/pkg/models/org_user.go b/pkg/models/org_user.go index afbb10386c8aa33..f456fa95373797f 100644 --- a/pkg/models/org_user.go +++ b/pkg/models/org_user.go @@ -7,9 +7,10 @@ import ( // Typed errors var ( - ErrInvalidRoleType = errors.New("Invalid role type") - ErrLastOrgAdmin = errors.New("Cannot remove last organization admin") - ErrOrgUserNotFound = errors.New("Cannot find the organization user") + ErrInvalidRoleType = errors.New("Invalid role type") + ErrLastOrgAdmin = errors.New("Cannot remove last organization admin") + ErrOrgUserNotFound = errors.New("Cannot find the organization user") + ErrOrgUserAlreadyAdded = errors.New("User is already added to organization") ) type RoleType string diff --git a/pkg/services/sqlstore/org_users.go b/pkg/services/sqlstore/org_users.go index 2e8fc40cb7c8d89..fdd671d0bfe21f6 100644 --- a/pkg/services/sqlstore/org_users.go +++ b/pkg/services/sqlstore/org_users.go @@ -19,6 +19,12 @@ func init() { func AddOrgUser(cmd *m.AddOrgUserCommand) error { return inTransaction(func(sess *xorm.Session) error { + // check if user exists + if res, err := sess.Query("SELECT 1 from org_user WHERE org_id=? and user_id=?", cmd.OrgId, cmd.UserId); err != nil { + return err + } else if len(res) == 1 { + return m.ErrOrgUserAlreadyAdded + } entity := m.OrgUser{ OrgId: cmd.OrgId, diff --git a/public/app/features/org/userInviteCtrl.js b/public/app/features/org/userInviteCtrl.js index ad343af5bff6594..52b307612b3fec6 100644 --- a/public/app/features/org/userInviteCtrl.js +++ b/public/app/features/org/userInviteCtrl.js @@ -7,7 +7,7 @@ function (angular, _) { var module = angular.module('grafana.controllers'); - module.controller('UserInviteCtrl', function($scope, backendSrv, $q) { + module.controller('UserInviteCtrl', function($scope, backendSrv) { $scope.invites = [ {name: '', email: '', role: 'Editor'}, @@ -26,17 +26,23 @@ function (angular, _) { $scope.sendInvites = function() { if (!$scope.inviteForm.$valid) { return; } + $scope.sendSingleInvite(0); + }; - var promises = _.map($scope.invites, function(invite) { - invite.skipEmails = $scope.options.skipEmails; - return backendSrv.post('/api/org/invites', invite); - }); + $scope.sendSingleInvite = function(index) { + var invite = $scope.invites[index]; + invite.skipEmails = $scope.options.skipEmails; - $q.all(promises).then(function() { - $scope.invitesSent(); - }); + return backendSrv.post('/api/org/invites', invite).finally(function() { + index += 1; - $scope.dismiss(); + if (index === $scope.invites.length) { + $scope.invitesSent(); + $scope.dismiss(); + } else { + $scope.sendSingleInvite(index); + } + }); }; }); });