MM-46528_Verify Invitation Flow Tracking Telemetry (#21227)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
679c23d235
Коммит
757c4e041a
@@ -160,10 +160,10 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request)
|
|||||||
if len(goodEmails) > 0 {
|
if len(goodEmails) > 0 {
|
||||||
var invitesWithErrors2 []*model.EmailInviteWithError
|
var invitesWithErrors2 []*model.EmailInviteWithError
|
||||||
if len(channels) > 0 {
|
if len(channels) > 0 {
|
||||||
invitesWithErrors2, err = c.App.Srv().EmailService.SendInviteEmailsToTeamAndChannels(team, channels, "Administrator", "mmctl "+model.NewId(), nil, goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, memberInvite.Message, true)
|
invitesWithErrors2, err = c.App.Srv().EmailService.SendInviteEmailsToTeamAndChannels(team, channels, "Administrator", "mmctl "+model.NewId(), nil, goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, memberInvite.Message, true, true, false)
|
||||||
invitesWithErrors = append(invitesWithErrors, invitesWithErrors2...)
|
invitesWithErrors = append(invitesWithErrors, invitesWithErrors2...)
|
||||||
} else {
|
} else {
|
||||||
err = c.App.Srv().EmailService.SendInviteEmails(team, "Administrator", "mmctl "+model.NewId(), goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, false)
|
err = c.App.Srv().EmailService.SendInviteEmails(team, "Administrator", "mmctl "+model.NewId(), goodEmails, *c.App.Config().ServiceSettings.SiteURL, nil, false, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -200,7 +200,7 @@ func localInviteUsersToTeam(c *Context, w http.ResponseWriter, r *http.Request)
|
|||||||
c.Err = model.NewAppError("localInviteUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]any{"Addresses": s}, "", http.StatusBadRequest)
|
c.Err = model.NewAppError("localInviteUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]any{"Addresses": s}, "", http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err := c.App.Srv().EmailService.SendInviteEmails(team, "Administrator", "mmctl "+model.NewId(), emailList, *c.App.Config().ServiceSettings.SiteURL, nil, false)
|
err := c.App.Srv().EmailService.SendInviteEmails(team, "Administrator", "mmctl "+model.NewId(), emailList, *c.App.Config().ServiceSettings.SiteURL, nil, false, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(err, email.NoRateLimiterError):
|
case errors.Is(err, email.NoRateLimiterError):
|
||||||
|
|||||||
@@ -1143,6 +1143,7 @@ type AppIface interface {
|
|||||||
UpsertGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError)
|
UpsertGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError)
|
||||||
UserAlreadyNotifiedOnRequiredFeature(user string, feature model.MattermostPaidFeature) bool
|
UserAlreadyNotifiedOnRequiredFeature(user string, feature model.MattermostPaidFeature) bool
|
||||||
UserCanSeeOtherUser(userID string, otherUserId string) (bool, *model.AppError)
|
UserCanSeeOtherUser(userID string, otherUserId string) (bool, *model.AppError)
|
||||||
|
UserIsFirstAdmin(user *model.User) bool
|
||||||
VerifyEmailFromToken(c request.CTX, userSuppliedTokenString string) *model.AppError
|
VerifyEmailFromToken(c request.CTX, userSuppliedTokenString string) *model.AppError
|
||||||
VerifyUserEmail(userID, email string) *model.AppError
|
VerifyUserEmail(userID, email string) *model.AppError
|
||||||
ViewChannel(c request.CTX, view *model.ChannelView, userID string, currentSessionId string, collapsedThreadsSupported bool) (map[string]int64, *model.AppError)
|
ViewChannel(c request.CTX, view *model.ChannelView, userID string, currentSessionId string, collapsedThreadsSupported bool) (map[string]int64, *model.AppError)
|
||||||
|
|||||||
@@ -410,7 +410,17 @@ func (es *Service) SendMfaChangeEmail(email string, activated bool, locale, site
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) SendInviteEmails(team *model.Team, senderName string, senderUserId string, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, errorWhenNotSent bool) error {
|
func (es *Service) SendInviteEmails(
|
||||||
|
team *model.Team,
|
||||||
|
senderName string,
|
||||||
|
senderUserId string,
|
||||||
|
invites []string,
|
||||||
|
siteURL string,
|
||||||
|
reminderData *model.TeamInviteReminderData,
|
||||||
|
errorWhenNotSent bool,
|
||||||
|
isSystemAdmin bool,
|
||||||
|
isFirstAdmin bool,
|
||||||
|
) error {
|
||||||
if es.perHourEmailRateLimiter == nil {
|
if es.perHourEmailRateLimiter == nil {
|
||||||
return NoRateLimiterError
|
return NoRateLimiterError
|
||||||
}
|
}
|
||||||
@@ -466,7 +476,8 @@ func (es *Service) SendInviteEmails(team *model.Team, senderName string, senderU
|
|||||||
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
data.Props["ButtonURL"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s", siteURL, url.QueryEscape(tokenData), url.QueryEscape(token.Token))
|
|
||||||
|
data.Props["ButtonURL"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s&sbr=%s", siteURL, url.QueryEscape(tokenData), url.QueryEscape(token.Token), es.GetTrackFlowStartedByRole(isFirstAdmin, isSystemAdmin))
|
||||||
|
|
||||||
body, err := es.templatesContainer.RenderToString("invite_body", data)
|
body, err := es.templatesContainer.RenderToString("invite_body", data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -484,7 +495,19 @@ func (es *Service) SendInviteEmails(team *model.Team, senderName string, senderU
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (es *Service) SendGuestInviteEmails(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, message string, errorWhenNotSent bool) error {
|
func (es *Service) SendGuestInviteEmails(
|
||||||
|
team *model.Team,
|
||||||
|
channels []*model.Channel,
|
||||||
|
senderName string,
|
||||||
|
senderUserId string,
|
||||||
|
senderProfileImage []byte,
|
||||||
|
invites []string,
|
||||||
|
siteURL string,
|
||||||
|
message string,
|
||||||
|
errorWhenNotSent bool,
|
||||||
|
isSystemAdmin bool,
|
||||||
|
isFirstAdmin bool,
|
||||||
|
) error {
|
||||||
if es.perHourEmailRateLimiter == nil {
|
if es.perHourEmailRateLimiter == nil {
|
||||||
return NoRateLimiterError
|
return NoRateLimiterError
|
||||||
}
|
}
|
||||||
@@ -545,7 +568,8 @@ func (es *Service) SendGuestInviteEmails(team *model.Team, channels []*model.Cha
|
|||||||
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
data.Props["ButtonURL"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s", siteURL, url.QueryEscape(tokenData), url.QueryEscape(token.Token))
|
|
||||||
|
data.Props["ButtonURL"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s&sbr=%s", siteURL, url.QueryEscape(tokenData), url.QueryEscape(token.Token), es.GetTrackFlowStartedByRole(isFirstAdmin, isSystemAdmin))
|
||||||
|
|
||||||
if !*es.config().EmailSettings.SendEmailNotifications {
|
if !*es.config().EmailSettings.SendEmailNotifications {
|
||||||
mlog.Info("sending invitation ", mlog.String("to", invite), mlog.String("link", data.Props["ButtonURL"].(string)))
|
mlog.Info("sending invitation ", mlog.String("to", invite), mlog.String("link", data.Props["ButtonURL"].(string)))
|
||||||
@@ -597,6 +621,8 @@ func (es *Service) SendInviteEmailsToTeamAndChannels(
|
|||||||
reminderData *model.TeamInviteReminderData,
|
reminderData *model.TeamInviteReminderData,
|
||||||
message string,
|
message string,
|
||||||
errorWhenNotSent bool,
|
errorWhenNotSent bool,
|
||||||
|
isSystemAdmin bool,
|
||||||
|
isFirstAdmin bool,
|
||||||
) ([]*model.EmailInviteWithError, error) {
|
) ([]*model.EmailInviteWithError, error) {
|
||||||
if es.perHourEmailRateLimiter == nil {
|
if es.perHourEmailRateLimiter == nil {
|
||||||
return nil, NoRateLimiterError
|
return nil, NoRateLimiterError
|
||||||
@@ -694,7 +720,8 @@ func (es *Service) SendInviteEmailsToTeamAndChannels(
|
|||||||
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
mlog.Error("Failed to send invite email successfully ", mlog.Err(err))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
data.Props["ButtonURL"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s", siteURL, url.QueryEscape(tokenData), url.QueryEscape(token.Token))
|
|
||||||
|
data.Props["ButtonURL"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&t=%s&sbr=%s", siteURL, url.QueryEscape(tokenData), url.QueryEscape(token.Token), es.GetTrackFlowStartedByRole(isFirstAdmin, isSystemAdmin))
|
||||||
|
|
||||||
senderPhoto := ""
|
senderPhoto := ""
|
||||||
embeddedFiles := make(map[string]io.Reader)
|
embeddedFiles := make(map[string]io.Reader)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
t.Run("SendInviteEmails", func(t *testing.T) {
|
t.Run("SendInviteEmails", func(t *testing.T) {
|
||||||
mail.DeleteMailBox(emailTo)
|
mail.DeleteMailBox(emailTo)
|
||||||
|
|
||||||
err := th.service.SendInviteEmails(th.BasicTeam, "test-user", th.BasicUser.Id, []string{emailTo}, "http://testserver", nil, false)
|
err := th.service.SendInviteEmails(th.BasicTeam, "test-user", th.BasicUser.Id, []string{emailTo}, "http://testserver", nil, false, false, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
verifyMailbox(t)
|
verifyMailbox(t)
|
||||||
@@ -93,10 +93,10 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
*cfg.EmailSettings.SMTPPort = originalPort
|
*cfg.EmailSettings.SMTPPort = originalPort
|
||||||
})
|
})
|
||||||
|
|
||||||
err := th.service.SendInviteEmails(th.BasicTeam, "test-user", th.BasicUser.Id, []string{emailTo}, "http://testserver", nil, true)
|
err := th.service.SendInviteEmails(th.BasicTeam, "test-user", th.BasicUser.Id, []string{emailTo}, "http://testserver", nil, true, false, false)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
err = th.service.SendInviteEmails(th.BasicTeam, "test-user", th.BasicUser.Id, []string{emailTo}, "http://testserver", nil, false)
|
err = th.service.SendInviteEmails(th.BasicTeam, "test-user", th.BasicUser.Id, []string{emailTo}, "http://testserver", nil, false, false, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -113,6 +113,8 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
"http://testserver",
|
"http://testserver",
|
||||||
"hello world",
|
"hello world",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -140,6 +142,8 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
"http://testserver",
|
"http://testserver",
|
||||||
"hello world",
|
"hello world",
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -153,6 +157,8 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
"http://testserver",
|
"http://testserver",
|
||||||
"hello world",
|
"hello world",
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
@@ -172,6 +178,8 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
"http://testserver",
|
"http://testserver",
|
||||||
message,
|
message,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -180,6 +188,66 @@ func TestSendInviteEmails(t *testing.T) {
|
|||||||
require.Contains(t, email.Body.HTML, "sanitized message")
|
require.Contains(t, email.Body.HTML, "sanitized message")
|
||||||
require.Contains(t, email.Body.Text, "sanitized message")
|
require.Contains(t, email.Body.Text, "sanitized message")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("SendInviteEmails should contain button URL with 'started by role' param for system user", func(t *testing.T) {
|
||||||
|
mail.DeleteMailBox(emailTo)
|
||||||
|
|
||||||
|
err := th.service.SendInviteEmails(
|
||||||
|
th.BasicTeam,
|
||||||
|
"test-user",
|
||||||
|
th.BasicUser.Id,
|
||||||
|
[]string{emailTo},
|
||||||
|
"http://testserver",
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
email := retrieveEmail(t)
|
||||||
|
require.Contains(t, email.Body.HTML, "&sbr=su")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("SendInviteEmails should contain button URL with 'started by role' param for system admin", func(t *testing.T) {
|
||||||
|
mail.DeleteMailBox(emailTo)
|
||||||
|
|
||||||
|
err := th.service.SendInviteEmails(
|
||||||
|
th.BasicTeam,
|
||||||
|
"test-user",
|
||||||
|
th.BasicUser.Id,
|
||||||
|
[]string{emailTo},
|
||||||
|
"http://testserver",
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
email := retrieveEmail(t)
|
||||||
|
require.Contains(t, email.Body.HTML, "&sbr=sa")
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("SendInviteEmails should contain button URL with 'started by role' param for first system admin", func(t *testing.T) {
|
||||||
|
mail.DeleteMailBox(emailTo)
|
||||||
|
|
||||||
|
err := th.service.SendInviteEmails(
|
||||||
|
th.BasicTeam,
|
||||||
|
"test-user",
|
||||||
|
th.BasicUser.Id,
|
||||||
|
[]string{emailTo},
|
||||||
|
"http://testserver",
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
email := retrieveEmail(t)
|
||||||
|
require.Contains(t, email.Body.HTML, "&sbr=fa")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSendCloudUpgradedEmail(t *testing.T) {
|
func TestSendCloudUpgradedEmail(t *testing.T) {
|
||||||
|
|||||||
@@ -293,13 +293,13 @@ func (_m *ServiceInterface) SendEmailChangeVerifyEmail(newUserEmail string, loca
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendGuestInviteEmails provides a mock function with given fields: team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, message, errorWhenNotSent
|
// SendGuestInviteEmails provides a mock function with given fields: team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin
|
||||||
func (_m *ServiceInterface) SendGuestInviteEmails(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, message string, errorWhenNotSent bool) error {
|
func (_m *ServiceInterface) SendGuestInviteEmails(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, message string, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) error {
|
||||||
ret := _m.Called(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, message, errorWhenNotSent)
|
ret := _m.Called(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, string, bool) error); ok {
|
if rf, ok := ret.Get(0).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, string, bool, bool, bool) error); ok {
|
||||||
r0 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, message, errorWhenNotSent)
|
r0 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
@@ -307,13 +307,13 @@ func (_m *ServiceInterface) SendGuestInviteEmails(team *model.Team, channels []*
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendInviteEmails provides a mock function with given fields: team, senderName, senderUserId, invites, siteURL, reminderData, errorWhenNotSent
|
// SendInviteEmails provides a mock function with given fields: team, senderName, senderUserId, invites, siteURL, reminderData, errorWhenNotSent, isSystemAdmin, isFirstAdmin
|
||||||
func (_m *ServiceInterface) SendInviteEmails(team *model.Team, senderName string, senderUserId string, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, errorWhenNotSent bool) error {
|
func (_m *ServiceInterface) SendInviteEmails(team *model.Team, senderName string, senderUserId string, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) error {
|
||||||
ret := _m.Called(team, senderName, senderUserId, invites, siteURL, reminderData, errorWhenNotSent)
|
ret := _m.Called(team, senderName, senderUserId, invites, siteURL, reminderData, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(*model.Team, string, string, []string, string, *model.TeamInviteReminderData, bool) error); ok {
|
if rf, ok := ret.Get(0).(func(*model.Team, string, string, []string, string, *model.TeamInviteReminderData, bool, bool, bool) error); ok {
|
||||||
r0 = rf(team, senderName, senderUserId, invites, siteURL, reminderData, errorWhenNotSent)
|
r0 = rf(team, senderName, senderUserId, invites, siteURL, reminderData, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
@@ -321,13 +321,13 @@ func (_m *ServiceInterface) SendInviteEmails(team *model.Team, senderName string
|
|||||||
return r0
|
return r0
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendInviteEmailsToTeamAndChannels provides a mock function with given fields: team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent
|
// SendInviteEmailsToTeamAndChannels provides a mock function with given fields: team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin
|
||||||
func (_m *ServiceInterface) SendInviteEmailsToTeamAndChannels(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, message string, errorWhenNotSent bool) ([]*model.EmailInviteWithError, error) {
|
func (_m *ServiceInterface) SendInviteEmailsToTeamAndChannels(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, message string, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) ([]*model.EmailInviteWithError, error) {
|
||||||
ret := _m.Called(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent)
|
ret := _m.Called(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
|
|
||||||
var r0 []*model.EmailInviteWithError
|
var r0 []*model.EmailInviteWithError
|
||||||
if rf, ok := ret.Get(0).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool) []*model.EmailInviteWithError); ok {
|
if rf, ok := ret.Get(0).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool, bool, bool) []*model.EmailInviteWithError); ok {
|
||||||
r0 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent)
|
r0 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).([]*model.EmailInviteWithError)
|
r0 = ret.Get(0).([]*model.EmailInviteWithError)
|
||||||
@@ -335,8 +335,8 @@ func (_m *ServiceInterface) SendInviteEmailsToTeamAndChannels(team *model.Team,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool) error); ok {
|
if rf, ok := ret.Get(1).(func(*model.Team, []*model.Channel, string, string, []byte, []string, string, *model.TeamInviteReminderData, string, bool, bool, bool) error); ok {
|
||||||
r1 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent)
|
r1 = rf(team, channels, senderName, senderUserId, senderProfileImage, invites, siteURL, reminderData, message, errorWhenNotSent, isSystemAdmin, isFirstAdmin)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,9 +135,9 @@ type ServiceInterface interface {
|
|||||||
SendUserAccessTokenAddedEmail(email, locale, siteURL string) error
|
SendUserAccessTokenAddedEmail(email, locale, siteURL string) error
|
||||||
SendPasswordResetEmail(email string, token *model.Token, locale, siteURL string) (bool, error)
|
SendPasswordResetEmail(email string, token *model.Token, locale, siteURL string) (bool, error)
|
||||||
SendMfaChangeEmail(email string, activated bool, locale, siteURL string) error
|
SendMfaChangeEmail(email string, activated bool, locale, siteURL string) error
|
||||||
SendInviteEmails(team *model.Team, senderName string, senderUserId string, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, errorWhenNotSent bool) error
|
SendInviteEmails(team *model.Team, senderName string, senderUserId string, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) error
|
||||||
SendGuestInviteEmails(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, message string, errorWhenNotSent bool) error
|
SendGuestInviteEmails(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, message string, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) error
|
||||||
SendInviteEmailsToTeamAndChannels(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, message string, errorWhenNotSent bool) ([]*model.EmailInviteWithError, error)
|
SendInviteEmailsToTeamAndChannels(team *model.Team, channels []*model.Channel, senderName string, senderUserId string, senderProfileImage []byte, invites []string, siteURL string, reminderData *model.TeamInviteReminderData, message string, errorWhenNotSent bool, isSystemAdmin bool, isFirstAdmin bool) ([]*model.EmailInviteWithError, error)
|
||||||
SendDeactivateAccountEmail(email string, locale, siteURL string) error
|
SendDeactivateAccountEmail(email string, locale, siteURL string) error
|
||||||
SendNotificationMail(to, subject, htmlBody string) error
|
SendNotificationMail(to, subject, htmlBody string) error
|
||||||
SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string) error
|
SendMailWithEmbeddedFiles(to, subject, htmlBody string, embeddedFiles map[string]io.Reader, messageID string, inReplyTo string, references string) error
|
||||||
|
|||||||
@@ -34,3 +34,15 @@ func (es *Service) mailServiceConfig(replyToAddress string) *mail.SMTPConfig {
|
|||||||
}
|
}
|
||||||
return &cfg
|
return &cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (es *Service) GetTrackFlowStartedByRole(isFirstAdmin bool, isSystemAdmin bool) string {
|
||||||
|
trackFlowStartedByRole := "su"
|
||||||
|
|
||||||
|
if isFirstAdmin {
|
||||||
|
trackFlowStartedByRole = "fa"
|
||||||
|
} else if isSystemAdmin {
|
||||||
|
trackFlowStartedByRole = "sa"
|
||||||
|
}
|
||||||
|
|
||||||
|
return trackFlowStartedByRole
|
||||||
|
}
|
||||||
|
|||||||
@@ -18052,6 +18052,23 @@ func (a *OpenTracingAppLayer) UserCanSeeOtherUser(userID string, otherUserId str
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *OpenTracingAppLayer) UserIsFirstAdmin(user *model.User) bool {
|
||||||
|
origCtx := a.ctx
|
||||||
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UserIsFirstAdmin")
|
||||||
|
|
||||||
|
a.ctx = newCtx
|
||||||
|
a.app.Srv().Store.SetContext(newCtx)
|
||||||
|
defer func() {
|
||||||
|
a.app.Srv().Store.SetContext(origCtx)
|
||||||
|
a.ctx = origCtx
|
||||||
|
}()
|
||||||
|
|
||||||
|
defer span.Finish()
|
||||||
|
resultVar0 := a.app.UserIsFirstAdmin(user)
|
||||||
|
|
||||||
|
return resultVar0
|
||||||
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) UserIsInAdminRoleGroup(userID string, syncableID string, syncableType model.GroupSyncableType) (bool, *model.AppError) {
|
func (a *OpenTracingAppLayer) UserIsInAdminRoleGroup(userID string, syncableID string, syncableType model.GroupSyncableType) (bool, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UserIsInAdminRoleGroup")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UserIsInAdminRoleGroup")
|
||||||
|
|||||||
14
app/team.go
14
app/team.go
@@ -1461,13 +1461,15 @@ func (a *App) InviteNewUsersToTeamGracefully(memberInvite *model.MemberInvite, t
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
|
a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userIsFirstAdmin := a.UserIsFirstAdmin(user)
|
||||||
var eErr error
|
var eErr error
|
||||||
var invitesWithErrors2 []*model.EmailInviteWithError
|
var invitesWithErrors2 []*model.EmailInviteWithError
|
||||||
if len(channels) > 0 {
|
if len(channels) > 0 {
|
||||||
invitesWithErrors2, eErr = a.Srv().EmailService.SendInviteEmailsToTeamAndChannels(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), reminderData, memberInvite.Message, true)
|
invitesWithErrors2, eErr = a.Srv().EmailService.SendInviteEmailsToTeamAndChannels(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), reminderData, memberInvite.Message, true, user.IsSystemAdmin(), userIsFirstAdmin)
|
||||||
inviteListWithErrors = append(inviteListWithErrors, invitesWithErrors2...)
|
inviteListWithErrors = append(inviteListWithErrors, invitesWithErrors2...)
|
||||||
} else {
|
} else {
|
||||||
eErr = a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, goodEmails, a.GetSiteURL(), reminderData, true)
|
eErr = a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, goodEmails, a.GetSiteURL(), reminderData, true, user.IsSystemAdmin(), userIsFirstAdmin)
|
||||||
}
|
}
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
switch {
|
switch {
|
||||||
@@ -1587,7 +1589,8 @@ func (a *App) InviteGuestsToChannelsGracefully(teamID string, guestsInvite *mode
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
|
a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
|
||||||
}
|
}
|
||||||
eErr := a.Srv().EmailService.SendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), guestsInvite.Message, true)
|
|
||||||
|
eErr := a.Srv().EmailService.SendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), guestsInvite.Message, true, user.IsSystemAdmin(), a.UserIsFirstAdmin(user))
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(eErr, email.SendMailError):
|
case errors.Is(eErr, email.SendMailError):
|
||||||
@@ -1644,7 +1647,7 @@ func (a *App) InviteNewUsersToTeam(emailList []string, teamID, senderId string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
|
nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
|
||||||
eErr := a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL(), nil, false)
|
eErr := a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL(), nil, false, user.IsSystemAdmin(), a.UserIsFirstAdmin(user))
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(eErr, email.NoRateLimiterError):
|
case errors.Is(eErr, email.NoRateLimiterError):
|
||||||
@@ -1686,7 +1689,8 @@ func (a *App) InviteGuestsToChannels(teamID string, guestsInvite *model.GuestsIn
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
|
a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
|
||||||
}
|
}
|
||||||
eErr := a.Srv().EmailService.SendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, guestsInvite.Emails, a.GetSiteURL(), guestsInvite.Message, false)
|
|
||||||
|
eErr := a.Srv().EmailService.SendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, guestsInvite.Emails, a.GetSiteURL(), guestsInvite.Message, false, user.IsSystemAdmin(), a.UserIsFirstAdmin(user))
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
switch {
|
switch {
|
||||||
case errors.Is(eErr, email.NoRateLimiterError):
|
case errors.Is(eErr, email.NoRateLimiterError):
|
||||||
|
|||||||
@@ -1457,6 +1457,8 @@ func TestInviteNewUsersToTeamGracefully(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
mock.Anything,
|
mock.Anything,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
).Once().Return(nil)
|
).Once().Return(nil)
|
||||||
th.App.Srv().EmailService = &emailServiceMock
|
th.App.Srv().EmailService = &emailServiceMock
|
||||||
|
|
||||||
@@ -1479,6 +1481,8 @@ func TestInviteNewUsersToTeamGracefully(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
mock.Anything,
|
mock.Anything,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
).Once().Return(email.SendMailError)
|
).Once().Return(email.SendMailError)
|
||||||
th.App.Srv().EmailService = &emailServiceMock
|
th.App.Srv().EmailService = &emailServiceMock
|
||||||
|
|
||||||
@@ -1505,6 +1509,8 @@ func TestInviteNewUsersToTeamGracefully(t *testing.T) {
|
|||||||
mock.Anything,
|
mock.Anything,
|
||||||
mock.AnythingOfType("string"),
|
mock.AnythingOfType("string"),
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
).Once().Return([]*model.EmailInviteWithError{}, nil)
|
).Once().Return([]*model.EmailInviteWithError{}, nil)
|
||||||
th.App.Srv().EmailService = &emailServiceMock
|
th.App.Srv().EmailService = &emailServiceMock
|
||||||
|
|
||||||
@@ -1527,6 +1533,8 @@ func TestInviteNewUsersToTeamGracefully(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
mock.Anything,
|
mock.Anything,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
).Once().Return(nil)
|
).Once().Return(nil)
|
||||||
th.App.Srv().EmailService = &emailServiceMock
|
th.App.Srv().EmailService = &emailServiceMock
|
||||||
|
|
||||||
@@ -1557,6 +1565,8 @@ func TestInviteGuestsToChannelsGracefully(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
).Once().Return(nil)
|
).Once().Return(nil)
|
||||||
th.App.Srv().EmailService = &emailServiceMock
|
th.App.Srv().EmailService = &emailServiceMock
|
||||||
|
|
||||||
@@ -1581,6 +1591,8 @@ func TestInviteGuestsToChannelsGracefully(t *testing.T) {
|
|||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
).Once().Return(email.SendMailError)
|
).Once().Return(email.SendMailError)
|
||||||
th.App.Srv().EmailService = &emailServiceMock
|
th.App.Srv().EmailService = &emailServiceMock
|
||||||
|
|
||||||
|
|||||||
22
app/user.go
22
app/user.go
@@ -2671,3 +2671,25 @@ func getProfileImagePath(userID string) string {
|
|||||||
func getProfileImageDirectory(userID string) string {
|
func getProfileImageDirectory(userID string) string {
|
||||||
return filepath.Join("users", userID)
|
return filepath.Join("users", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) UserIsFirstAdmin(user *model.User) bool {
|
||||||
|
if !user.IsSystemAdmin() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
systemAdminUsers, errServer := a.Srv().Store.User().GetSystemAdminProfiles()
|
||||||
|
if errServer != nil {
|
||||||
|
mlog.Warn("Failed to get system admins to check for first admin from Mattermost.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, systemAdminUser := range systemAdminUsers {
|
||||||
|
systemAdminUser := systemAdminUser
|
||||||
|
|
||||||
|
if systemAdminUser.CreateAt < user.CreateAt {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user