github.com/mattermost/mattermost-server/v5@v5.39.3/jobs/resend_invitation_email/worker.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  package resend_invitation_email
     4  
     5  import (
     6  	"encoding/json"
     7  	"net/http"
     8  	"os"
     9  	"strconv"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/app"
    12  	"github.com/mattermost/mattermost-server/v5/model"
    13  	"github.com/mattermost/mattermost-server/v5/shared/mlog"
    14  )
    15  
    16  const TwentyFourHoursInMillis int64 = 86400000
    17  
    18  type ResendInvitationEmailWorker struct {
    19  	name    string
    20  	stop    chan bool
    21  	stopped chan bool
    22  	jobs    chan model.Job
    23  	App     *app.App
    24  }
    25  
    26  func (rse *ResendInvitationEmailJobInterfaceImpl) MakeWorker() model.Worker {
    27  	worker := ResendInvitationEmailWorker{
    28  		name:    ResendInvitationEmailJob,
    29  		stop:    make(chan bool, 1),
    30  		stopped: make(chan bool, 1),
    31  		jobs:    make(chan model.Job),
    32  		App:     rse.App,
    33  	}
    34  	return &worker
    35  }
    36  
    37  func (rseworker *ResendInvitationEmailWorker) Run() {
    38  	mlog.Debug("Worker started", mlog.String("worker", rseworker.name))
    39  
    40  	defer func() {
    41  		mlog.Debug("Worker finished", mlog.String("worker", rseworker.name))
    42  		rseworker.stopped <- true
    43  	}()
    44  
    45  	for {
    46  		select {
    47  		case <-rseworker.stop:
    48  			mlog.Debug("Worker received stop signal", mlog.String("worker", rseworker.name))
    49  			return
    50  		case job := <-rseworker.jobs:
    51  			mlog.Debug("Worker received a new candidate job.", mlog.String("worker", rseworker.name))
    52  			rseworker.DoJob(&job)
    53  		}
    54  	}
    55  }
    56  
    57  func (rseworker *ResendInvitationEmailWorker) Stop() {
    58  	mlog.Debug("Worker stopping", mlog.String("worker", rseworker.name))
    59  	rseworker.stop <- true
    60  	<-rseworker.stopped
    61  }
    62  
    63  func (rseworker *ResendInvitationEmailWorker) JobChannel() chan<- model.Job {
    64  	return rseworker.jobs
    65  }
    66  
    67  func (rseworker *ResendInvitationEmailWorker) cleanEmailData(emailStringData string) ([]string, error) {
    68  	// emailStringData looks like this ["user1@gmail.com","user2@gmail.com"]
    69  	emails := []string{}
    70  	err := json.Unmarshal([]byte(emailStringData), &emails)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	return emails, nil
    76  }
    77  
    78  func (rseworker *ResendInvitationEmailWorker) removeAlreadyJoined(teamID string, emailList []string) []string {
    79  	var notJoinedYet []string
    80  	for _, email := range emailList {
    81  		// check if the user with this email is on the system already
    82  		user, appErr := rseworker.App.GetUserByEmail(email)
    83  		if appErr != nil {
    84  			notJoinedYet = append(notJoinedYet, email)
    85  			continue
    86  		}
    87  		// now we check if they are part of the team already
    88  		userID := []string{user.Id}
    89  		members, appErr := rseworker.App.GetTeamMembersByIds(teamID, userID, nil)
    90  		if len(members) == 0 || appErr != nil {
    91  			notJoinedYet = append(notJoinedYet, email)
    92  		}
    93  	}
    94  
    95  	return notJoinedYet
    96  }
    97  
    98  func (rseworker *ResendInvitationEmailWorker) DoJob(job *model.Job) {
    99  	scheduledAt, _ := strconv.ParseInt(job.Data["scheduledAt"], 10, 64)
   100  	now := model.GetMillis()
   101  
   102  	elapsedTimeSinceSchedule := now - scheduledAt
   103  
   104  	var DurationInMillis int64
   105  
   106  	duration := os.Getenv("MM_RESEND_INVITATION_EMAIL_JOB_DURATION")
   107  
   108  	DurationInMillis, parseError := strconv.ParseInt(duration, 10, 64)
   109  	if parseError != nil {
   110  		// default to 24 hours
   111  		DurationInMillis = TwentyFourHoursInMillis
   112  	}
   113  
   114  	if elapsedTimeSinceSchedule > DurationInMillis {
   115  		teamID := job.Data["teamID"]
   116  		emailListData := job.Data["emailList"]
   117  
   118  		emailList, err := rseworker.cleanEmailData(emailListData)
   119  		if err != nil {
   120  			appErr := model.NewAppError("worker: "+rseworker.name, "job_id: "+job.Id, nil, err.Error(), http.StatusInternalServerError)
   121  			mlog.Error("Worker: Failed to clean emails string data", mlog.String("worker", rseworker.name), mlog.String("job_id", job.Id), mlog.String("error", appErr.Error()))
   122  			rseworker.setJobError(job, appErr)
   123  		}
   124  
   125  		emailList = rseworker.removeAlreadyJoined(teamID, emailList)
   126  
   127  		_, appErr := rseworker.App.InviteNewUsersToTeamGracefully(emailList, teamID, job.Data["senderID"])
   128  		if appErr != nil {
   129  			mlog.Error("Worker: Failed to send emails", mlog.String("worker", rseworker.name), mlog.String("job_id", job.Id), mlog.String("error", appErr.Error()))
   130  			rseworker.setJobError(job, appErr)
   131  		}
   132  		rseworker.setJobSuccess(job)
   133  	}
   134  
   135  }
   136  
   137  func (rseworker *ResendInvitationEmailWorker) setJobSuccess(job *model.Job) {
   138  	if err := rseworker.App.Srv().Jobs.SetJobSuccess(job); err != nil {
   139  		mlog.Error("Worker: Failed to set success for job", mlog.String("worker", rseworker.name), mlog.String("job_id", job.Id), mlog.String("error", err.Error()))
   140  		rseworker.setJobError(job, err)
   141  	}
   142  }
   143  
   144  func (rseworker *ResendInvitationEmailWorker) setJobError(job *model.Job, appError *model.AppError) {
   145  	if err := rseworker.App.Srv().Jobs.SetJobError(job, appError); err != nil {
   146  		mlog.Error("Worker: Failed to set job error", mlog.String("worker", rseworker.name), mlog.String("job_id", job.Id), mlog.String("error", err.Error()))
   147  	}
   148  }