mirror of
https://github.com/hanzoai/team.git
synced 2026-11-01 07:55:31 +00:00
* MM-64486: Remove telemetry Remove telemetry from Mattermost. We're no longer relying on Rudder upstream, and no longer making use of this information. * recover mock for SystemStore.Get * Fix TestClearPushNotificationSync by adding missing SystemStore mock The test was failing because the SystemStore mock was missing the Get() method that's required by the ServerId() function. Added the missing mock to return a StringMap with SystemServerId. * fix mocking issue * Remove now-unused telemetry and constants * Remove "Disable telemetry events" debug setting * Remove empty functions * Remove most "Telemetry tracking removed" comments * Remove remains of DataPrefetch telemetry * Remove now-unused prop from InviteMembersButton * Remove trackDotMenuEvent * Remove some more leftover comments * Remove lingering logic related to trackingLocation * Remove now-unused argument from useCopyText * Remove lingering telemetry references from PreparingWorkspace * fixup Remove trackDotMenuEvent * Remove lingering telemetry references from signup page and password check * Update snapshots and fix test broken by my changes * Fix unintended behavior change in thread list filtering Remove handleSetFilter wrapper that was accidentally modified during telemetry removal. The function was calling clear() when switching to unread filter, which was not the original behavior. Use setFilter directly instead, restoring the original functionality. * Remove unused useOpenDowngradeModal hook The useOpenDowngradeModal hook was not being used anywhere in the codebase. * Remove unused expandableLink from useExpandOverageUsersCheck The expandableLink return value was not being used by any components. * Re-add missing TeamLinkClicked performance telemetry The mark(Mark.TeamLinkClicked) call was accidentally removed from the handleSwitch function. This telemetry is needed for Looker-based performance tracking. * drop LogSettings.VerboseDiagnostics --------- Co-authored-by: Harrison Healey <[email protected]> Co-authored-by: Mattermost Build <[email protected]>
215 lines
6.9 KiB
Go
215 lines
6.9 KiB
Go
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
// See LICENSE.txt for license information.
|
|
package resend_invitation_email
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/mattermost/mattermost/server/public/model"
|
|
"github.com/mattermost/mattermost/server/public/shared/configservice"
|
|
"github.com/mattermost/mattermost/server/public/shared/mlog"
|
|
"github.com/mattermost/mattermost/server/public/shared/request"
|
|
"github.com/mattermost/mattermost/server/v8/channels/jobs"
|
|
"github.com/mattermost/mattermost/server/v8/channels/store"
|
|
)
|
|
|
|
const FourtyEightHoursInMillis int64 = 172800000
|
|
|
|
type AppIface interface {
|
|
configservice.ConfigService
|
|
GetUserByEmail(email string) (*model.User, *model.AppError)
|
|
GetTeamMembersByIds(teamID string, userIDs []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError)
|
|
InviteNewUsersToTeamGracefully(rctx request.CTX, memberInvite *model.MemberInvite, teamID, senderId string, reminderInterval string) ([]*model.EmailInviteWithError, *model.AppError)
|
|
}
|
|
|
|
type ResendInvitationEmailWorker struct {
|
|
name string
|
|
stop chan bool
|
|
stopped chan bool
|
|
jobs chan model.Job
|
|
jobServer *jobs.JobServer
|
|
logger mlog.LoggerIFace
|
|
app AppIface
|
|
store store.Store
|
|
}
|
|
|
|
func MakeWorker(jobServer *jobs.JobServer, app AppIface, store store.Store) *ResendInvitationEmailWorker {
|
|
const workerName = "ResendInvitationEmail"
|
|
worker := ResendInvitationEmailWorker{
|
|
name: workerName,
|
|
stop: make(chan bool, 1),
|
|
stopped: make(chan bool, 1),
|
|
jobs: make(chan model.Job),
|
|
jobServer: jobServer,
|
|
logger: jobServer.Logger().With(mlog.String("worker_name", workerName)),
|
|
app: app,
|
|
store: store,
|
|
}
|
|
return &worker
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) Run() {
|
|
rseworker.logger.Debug("Worker started")
|
|
|
|
defer func() {
|
|
rseworker.logger.Debug("Worker finished")
|
|
rseworker.stopped <- true
|
|
}()
|
|
|
|
for {
|
|
select {
|
|
case <-rseworker.stop:
|
|
rseworker.logger.Debug("Worker received stop signal")
|
|
return
|
|
case job := <-rseworker.jobs:
|
|
rseworker.DoJob(&job)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) IsEnabled(cfg *model.Config) bool {
|
|
return *cfg.ServiceSettings.EnableEmailInvitations
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) Stop() {
|
|
rseworker.logger.Debug("Worker stopping")
|
|
rseworker.stop <- true
|
|
<-rseworker.stopped
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) JobChannel() chan<- model.Job {
|
|
return rseworker.jobs
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) DoJob(job *model.Job) {
|
|
logger := rseworker.logger.With(jobs.JobLoggerFields(job)...)
|
|
logger.Debug("Worker: Received a new candidate job.")
|
|
defer rseworker.jobServer.HandleJobPanic(logger, job)
|
|
|
|
elapsedTimeSinceSchedule, DurationInMillis := rseworker.GetDurations(job)
|
|
if elapsedTimeSinceSchedule > DurationInMillis {
|
|
rseworker.ResendEmails(logger, job, "48")
|
|
rseworker.TearDown(logger, job)
|
|
}
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) setJobSuccess(logger mlog.LoggerIFace, job *model.Job) {
|
|
if err := rseworker.jobServer.SetJobSuccess(job); err != nil {
|
|
logger.Error("Worker: Failed to set success for job", mlog.Err(err))
|
|
rseworker.setJobError(logger, job, err)
|
|
}
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) setJobError(logger mlog.LoggerIFace, job *model.Job, appError *model.AppError) {
|
|
if err := rseworker.jobServer.SetJobError(job, appError); err != nil {
|
|
logger.Error("Worker: Failed to set job error", mlog.Err(err))
|
|
}
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) cleanEmailData(emailStringData string) ([]string, error) {
|
|
// emailStringData looks like this ["[email protected]","[email protected]"]
|
|
emails := []string{}
|
|
err := json.Unmarshal([]byte(emailStringData), &emails)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return emails, nil
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) cleanChannelsData(channelStringData string) ([]string, error) {
|
|
// channelStringData looks like this ["uuuiiiiidddd","uuuiiiiidddd"]
|
|
channels := []string{}
|
|
err := json.Unmarshal([]byte(channelStringData), &channels)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return channels, nil
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) removeAlreadyJoined(teamID string, emailList []string) []string {
|
|
var notJoinedYet []string
|
|
for _, email := range emailList {
|
|
// check if the user with this email is on the system already
|
|
user, appErr := rseworker.app.GetUserByEmail(email)
|
|
if appErr != nil {
|
|
notJoinedYet = append(notJoinedYet, email)
|
|
continue
|
|
}
|
|
// now we check if they are part of the team already
|
|
userID := []string{user.Id}
|
|
members, appErr := rseworker.app.GetTeamMembersByIds(teamID, userID, nil)
|
|
if len(members) == 0 || appErr != nil {
|
|
notJoinedYet = append(notJoinedYet, email)
|
|
}
|
|
}
|
|
|
|
return notJoinedYet
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) GetDurations(job *model.Job) (int64, int64) {
|
|
scheduledAt, _ := strconv.ParseInt(job.Data["scheduledAt"], 10, 64)
|
|
now := model.GetMillis()
|
|
|
|
elapsedTimeSinceSchedule := now - scheduledAt
|
|
|
|
duration := os.Getenv("MM_RESEND_INVITATION_EMAIL_JOB_DURATION")
|
|
DurationInMillis, parseError := strconv.ParseInt(duration, 10, 64)
|
|
if parseError != nil {
|
|
// default to 48 hours
|
|
DurationInMillis = FourtyEightHoursInMillis
|
|
}
|
|
|
|
return elapsedTimeSinceSchedule, DurationInMillis
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) TearDown(logger mlog.LoggerIFace, job *model.Job) {
|
|
if _, err := rseworker.store.System().PermanentDeleteByName(job.Id); err != nil {
|
|
logger.Error("Worker: Failed to tear down data", mlog.Err(err))
|
|
}
|
|
|
|
rseworker.setJobSuccess(logger, job)
|
|
}
|
|
|
|
func (rseworker *ResendInvitationEmailWorker) ResendEmails(logger mlog.LoggerIFace, job *model.Job, interval string) {
|
|
rctx := request.EmptyContext(logger)
|
|
|
|
teamID := job.Data["teamID"]
|
|
emailListData := job.Data["emailList"]
|
|
channelListData := job.Data["channelList"]
|
|
|
|
emailList, err := rseworker.cleanEmailData(emailListData)
|
|
if err != nil {
|
|
appErr := model.NewAppError("worker: "+rseworker.name, "job_id: "+job.Id, nil, "", http.StatusInternalServerError).Wrap(err)
|
|
logger.Error("Worker: Failed to clean emails string data", mlog.Err(appErr))
|
|
rseworker.setJobError(logger, job, appErr)
|
|
}
|
|
|
|
channelList, err := rseworker.cleanChannelsData(channelListData)
|
|
if err != nil {
|
|
appErr := model.NewAppError("worker: "+rseworker.name, "job_id: "+job.Id, nil, "", http.StatusInternalServerError).Wrap(err)
|
|
logger.Error("Worker: Failed to clean channel string data", mlog.Err(appErr))
|
|
rseworker.setJobError(logger, job, appErr)
|
|
}
|
|
|
|
emailList = rseworker.removeAlreadyJoined(teamID, emailList)
|
|
|
|
memberInvite := model.MemberInvite{
|
|
Emails: emailList,
|
|
}
|
|
|
|
if len(channelList) > 0 {
|
|
memberInvite.ChannelIds = channelList
|
|
}
|
|
|
|
_, appErr := rseworker.app.InviteNewUsersToTeamGracefully(rctx, &memberInvite, teamID, job.Data["senderID"], interval)
|
|
if appErr != nil {
|
|
logger.Error("Worker: Failed to send emails", mlog.Err(appErr))
|
|
rseworker.setJobError(logger, job, appErr)
|
|
}
|
|
}
|