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 }