github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/api4/job.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package api4
     5  
     6  import (
     7  	"net/http"
     8  	"path/filepath"
     9  	"strconv"
    10  	"time"
    11  
    12  	"github.com/masterhung0112/hk_server/v5/audit"
    13  	"github.com/masterhung0112/hk_server/v5/model"
    14  	"github.com/masterhung0112/hk_server/v5/shared/mlog"
    15  )
    16  
    17  func (api *API) InitJob() {
    18  	api.BaseRoutes.Jobs.Handle("", api.ApiSessionRequired(getJobs)).Methods("GET")
    19  	api.BaseRoutes.Jobs.Handle("", api.ApiSessionRequired(createJob)).Methods("POST")
    20  	api.BaseRoutes.Jobs.Handle("/{job_id:[A-Za-z0-9]+}", api.ApiSessionRequired(getJob)).Methods("GET")
    21  	api.BaseRoutes.Jobs.Handle("/{job_id:[A-Za-z0-9]+}/download", api.ApiSessionRequiredTrustRequester(downloadJob)).Methods("GET")
    22  	api.BaseRoutes.Jobs.Handle("/{job_id:[A-Za-z0-9]+}/cancel", api.ApiSessionRequired(cancelJob)).Methods("POST")
    23  	api.BaseRoutes.Jobs.Handle("/type/{job_type:[A-Za-z0-9_-]+}", api.ApiSessionRequired(getJobsByType)).Methods("GET")
    24  }
    25  
    26  func getJob(c *Context, w http.ResponseWriter, r *http.Request) {
    27  	c.RequireJobId()
    28  	if c.Err != nil {
    29  		return
    30  	}
    31  
    32  	job, err := c.App.GetJob(c.Params.JobId)
    33  	if err != nil {
    34  		c.Err = err
    35  		return
    36  	}
    37  
    38  	hasPermission, permissionRequired := c.App.SessionHasPermissionToReadJob(*c.AppContext.Session(), job.Type)
    39  	if permissionRequired == nil {
    40  		c.Err = model.NewAppError("getJob", "api.job.retrieve.nopermissions", nil, "", http.StatusBadRequest)
    41  		return
    42  	}
    43  	if !hasPermission {
    44  		c.SetPermissionError(permissionRequired)
    45  		return
    46  	}
    47  
    48  	w.Write([]byte(job.ToJson()))
    49  }
    50  
    51  func downloadJob(c *Context, w http.ResponseWriter, r *http.Request) {
    52  	config := c.App.Config()
    53  	const FilePath = "export"
    54  	const FileMime = "application/zip"
    55  
    56  	c.RequireJobId()
    57  	if c.Err != nil {
    58  		return
    59  	}
    60  
    61  	if !*config.MessageExportSettings.DownloadExportResults {
    62  		c.Err = model.NewAppError("downloadExportResultsNotEnabled", "app.job.download_export_results_not_enabled", nil, "", http.StatusNotImplemented)
    63  		return
    64  	}
    65  
    66  	job, err := c.App.GetJob(c.Params.JobId)
    67  	if err != nil {
    68  		c.Err = err
    69  		return
    70  	}
    71  
    72  	// Currently, this endpoint only supports downloading the compliance report.
    73  	// If you need to download another job type, you will need to alter this section of the code to accommodate it.
    74  	if job.Type == model.JOB_TYPE_MESSAGE_EXPORT && !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT) {
    75  		c.SetPermissionError(model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT)
    76  		return
    77  	} else if job.Type != model.JOB_TYPE_MESSAGE_EXPORT {
    78  		c.Err = model.NewAppError("unableToDownloadJob", "api.job.unable_to_download_job.incorrect_job_type", nil, "", http.StatusBadRequest)
    79  		return
    80  	}
    81  
    82  	isDownloadable, _ := strconv.ParseBool(job.Data["is_downloadable"])
    83  	if !isDownloadable {
    84  		c.Err = model.NewAppError("unableToDownloadJob", "api.job.unable_to_download_job", nil, "", http.StatusBadRequest)
    85  		return
    86  	}
    87  
    88  	fileName := job.Id + ".zip"
    89  	filePath := filepath.Join(FilePath, fileName)
    90  	fileReader, err := c.App.FileReader(filePath)
    91  	if err != nil {
    92  		c.Err = err
    93  		c.Err.StatusCode = http.StatusNotFound
    94  		return
    95  	}
    96  	defer fileReader.Close()
    97  
    98  	// We are able to pass 0 for content size due to the fact that Golang's serveContent (https://golang.org/src/net/http/fs.go)
    99  	// already sets that for us
   100  	writeFileResponse(fileName, FileMime, 0, time.Unix(0, job.LastActivityAt*int64(1000*1000)), *c.App.Config().ServiceSettings.WebserverMode, fileReader, true, w, r)
   101  }
   102  
   103  func createJob(c *Context, w http.ResponseWriter, r *http.Request) {
   104  	job := model.JobFromJson(r.Body)
   105  	if job == nil {
   106  		c.SetInvalidParam("job")
   107  		return
   108  	}
   109  
   110  	auditRec := c.MakeAuditRecord("createJob", audit.Fail)
   111  	defer c.LogAuditRec(auditRec)
   112  	auditRec.AddMeta("job", job)
   113  
   114  	hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.AppContext.Session(), job)
   115  	if permissionRequired == nil {
   116  		c.Err = model.NewAppError("unableToCreateJob", "api.job.unable_to_create_job.incorrect_job_type", nil, "", http.StatusBadRequest)
   117  		return
   118  	}
   119  
   120  	if !hasPermission {
   121  		c.SetPermissionError(permissionRequired)
   122  		return
   123  	}
   124  
   125  	job, err := c.App.CreateJob(job)
   126  	if err != nil {
   127  		c.Err = err
   128  		return
   129  	}
   130  
   131  	auditRec.Success()
   132  	auditRec.AddMeta("job", job) // overwrite meta
   133  
   134  	w.WriteHeader(http.StatusCreated)
   135  	w.Write([]byte(job.ToJson()))
   136  }
   137  
   138  func getJobs(c *Context, w http.ResponseWriter, r *http.Request) {
   139  	if c.Err != nil {
   140  		return
   141  	}
   142  
   143  	var validJobTypes []string
   144  	for _, jobType := range model.ALL_JOB_TYPES {
   145  		hasPermission, permissionRequired := c.App.SessionHasPermissionToReadJob(*c.AppContext.Session(), jobType)
   146  		if permissionRequired == nil {
   147  			mlog.Warn("The job types of a job you are trying to retrieve does not contain permissions", mlog.String("jobType", jobType))
   148  			continue
   149  		}
   150  		if hasPermission {
   151  			validJobTypes = append(validJobTypes, jobType)
   152  		}
   153  	}
   154  	if len(validJobTypes) == 0 {
   155  		c.SetPermissionError()
   156  		return
   157  	}
   158  
   159  	jobs, err := c.App.GetJobsByTypesPage(validJobTypes, c.Params.Page, c.Params.PerPage)
   160  	if err != nil {
   161  		c.Err = err
   162  		return
   163  	}
   164  
   165  	w.Write([]byte(model.JobsToJson(jobs)))
   166  }
   167  
   168  func getJobsByType(c *Context, w http.ResponseWriter, r *http.Request) {
   169  	c.RequireJobType()
   170  	if c.Err != nil {
   171  		return
   172  	}
   173  
   174  	hasPermission, permissionRequired := c.App.SessionHasPermissionToReadJob(*c.AppContext.Session(), c.Params.JobType)
   175  	if permissionRequired == nil {
   176  		c.Err = model.NewAppError("getJobsByType", "api.job.retrieve.nopermissions", nil, "", http.StatusBadRequest)
   177  		return
   178  	}
   179  	if !hasPermission {
   180  		c.SetPermissionError(permissionRequired)
   181  		return
   182  	}
   183  
   184  	jobs, err := c.App.GetJobsByTypePage(c.Params.JobType, c.Params.Page, c.Params.PerPage)
   185  	if err != nil {
   186  		c.Err = err
   187  		return
   188  	}
   189  
   190  	w.Write([]byte(model.JobsToJson(jobs)))
   191  }
   192  
   193  func cancelJob(c *Context, w http.ResponseWriter, r *http.Request) {
   194  	c.RequireJobId()
   195  	if c.Err != nil {
   196  		return
   197  	}
   198  
   199  	auditRec := c.MakeAuditRecord("cancelJob", audit.Fail)
   200  	defer c.LogAuditRec(auditRec)
   201  	auditRec.AddMeta("job_id", c.Params.JobId)
   202  
   203  	job, err := c.App.GetJob(c.Params.JobId)
   204  	if err != nil {
   205  		c.Err = err
   206  		return
   207  	}
   208  
   209  	// if permission to create, permission to cancel, same permission
   210  	hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.AppContext.Session(), job)
   211  	if permissionRequired == nil {
   212  		c.Err = model.NewAppError("unableToCancelJob", "api.job.unable_to_create_job.incorrect_job_type", nil, "", http.StatusBadRequest)
   213  		return
   214  	}
   215  
   216  	if !hasPermission {
   217  		c.SetPermissionError(permissionRequired)
   218  		return
   219  	}
   220  
   221  	if err := c.App.CancelJob(c.Params.JobId); err != nil {
   222  		c.Err = err
   223  		return
   224  	}
   225  
   226  	auditRec.Success()
   227  
   228  	ReturnStatusOK(w)
   229  }