handlers.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package scheduler
  2. import (
  3. "encoding/json"
  4. "io/ioutil"
  5. "net/http"
  6. "path/filepath"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/tidwall/pretty"
  11. )
  12. //List all the jobs related to the given user
  13. func (a *Scheduler) HandleListJobs(w http.ResponseWriter, r *http.Request) {
  14. userinfo, err := a.userHandler.GetUserInfoFromRequest(w, r)
  15. if err != nil {
  16. sendErrorResponse(w, "User not logged in")
  17. return
  18. }
  19. //Get username from user info
  20. username := userinfo.Username
  21. isAdmin := userinfo.IsAdmin()
  22. //Check if the user request list all
  23. listAll := false
  24. la, _ := mv(r, "listall", false)
  25. if la == "true" && isAdmin {
  26. listAll = true
  27. }
  28. //Find the scheduled task that belongs to this user
  29. userCreatedJobs := []*Job{}
  30. for _, thisJob := range a.jobs {
  31. if listAll {
  32. //List all the user jobs.
  33. userCreatedJobs = append(userCreatedJobs, thisJob)
  34. } else {
  35. //Only list user's job
  36. if thisJob.Creator == username {
  37. userCreatedJobs = append(userCreatedJobs, thisJob)
  38. }
  39. }
  40. }
  41. //Return the values as json
  42. js, err := json.Marshal(userCreatedJobs)
  43. sendJSONResponse(w, string(js))
  44. }
  45. func (a *Scheduler) HandleAddJob(w http.ResponseWriter, r *http.Request) {
  46. userinfo, err := a.userHandler.GetUserInfoFromRequest(w, r)
  47. if err != nil {
  48. sendErrorResponse(w, "User not logged in")
  49. return
  50. }
  51. //Get required paramaters
  52. taskName, err := mv(r, "name", true)
  53. if err != nil {
  54. sendErrorResponse(w, "Invalid task name")
  55. return
  56. }
  57. //Check taskname length valid
  58. if len(taskName) > 32 {
  59. sendErrorResponse(w, "Task name must be shorter than 32 characters")
  60. return
  61. }
  62. //Check if the name already existsed
  63. for _, runningJob := range a.jobs {
  64. if runningJob.Name == taskName {
  65. sendErrorResponse(w, "Task Name already occupied")
  66. return
  67. }
  68. }
  69. scriptpath, err := mv(r, "path", true)
  70. if err != nil {
  71. sendErrorResponse(w, "Invalid script path")
  72. return
  73. }
  74. //Can be empty
  75. jobDescription, _ := mv(r, "desc", true)
  76. fsh, err := userinfo.GetFileSystemHandlerFromVirtualPath(scriptpath)
  77. if err != nil {
  78. sendErrorResponse(w, err.Error())
  79. return
  80. }
  81. fshAbs := fsh.FileSystemAbstraction
  82. realScriptPath, err := fshAbs.VirtualPathToRealPath(scriptpath, userinfo.Username)
  83. if err != nil {
  84. sendErrorResponse(w, err.Error())
  85. return
  86. }
  87. //Check if the user has permission to create this script
  88. if filepath.Ext(realScriptPath) != ".js" && filepath.Ext(realScriptPath) != ".agi" {
  89. //Require admin permission
  90. if !userinfo.IsAdmin() {
  91. sendErrorResponse(w, "Admin permission required for scheduling non AGI script")
  92. return
  93. }
  94. }
  95. interval := int64(86400) //default 1 day in seconds
  96. intervalString, err := mv(r, "interval", true)
  97. if err != nil {
  98. //Default 1 day
  99. } else {
  100. //Parse the intervalString into int
  101. intervalInt, err := strconv.ParseInt(intervalString, 10, 64)
  102. if err != nil {
  103. //Failed to parse interval to int
  104. sendErrorResponse(w, "Invalid interval")
  105. return
  106. }
  107. interval = intervalInt
  108. }
  109. baseUnixTime := time.Now().Unix()
  110. baseTimeString, err := mv(r, "base", true)
  111. if err != nil {
  112. //Use curent timestamp as base
  113. } else {
  114. baseTimeInt, err := strconv.Atoi(baseTimeString)
  115. if err != nil {
  116. //Failed to parse interval to int
  117. sendErrorResponse(w, "Invalid Base Time")
  118. return
  119. }
  120. baseUnixTime = int64(baseTimeInt)
  121. }
  122. //Create a new job
  123. newJob := Job{
  124. Name: taskName,
  125. Creator: userinfo.Username,
  126. Admin: userinfo.IsAdmin(),
  127. Description: jobDescription,
  128. ExecutionInterval: int64(interval),
  129. BaseTime: baseUnixTime,
  130. ScriptFile: realScriptPath,
  131. FshID: fsh.UUID,
  132. }
  133. //Write current job lists to file
  134. a.jobs = append(a.jobs, &newJob)
  135. js, _ := json.MarshalIndent(a.jobs, "", " ")
  136. ioutil.WriteFile(a.cronfile, js, 0755)
  137. //OK
  138. sendOK(w)
  139. }
  140. func (a *Scheduler) HandleJobRemoval(w http.ResponseWriter, r *http.Request) {
  141. userinfo, err := a.userHandler.GetUserInfoFromRequest(w, r)
  142. if err != nil {
  143. sendErrorResponse(w, "User not logged in")
  144. return
  145. }
  146. //Get required paramaters
  147. taskName, err := mv(r, "name", true)
  148. if err != nil {
  149. sendErrorResponse(w, "Invalid task name")
  150. return
  151. }
  152. //Check if Job exists
  153. if !a.JobExists(taskName) {
  154. //Job with that name not exists
  155. sendErrorResponse(w, "Job not exists")
  156. return
  157. }
  158. targetJob := a.GetScheduledJobByName(taskName)
  159. //Job exists. Check if the job is created by the user.
  160. //User can only remove job created by himself or all job is he is admin
  161. allowRemove := false
  162. if userinfo.IsAdmin() == false && targetJob.Creator == userinfo.Username {
  163. allowRemove = true
  164. } else if userinfo.IsAdmin() == true {
  165. allowRemove = true
  166. }
  167. if !allowRemove {
  168. sendErrorResponse(w, "Permission Denied")
  169. return
  170. }
  171. //Ok. Remove Job from the list
  172. a.RemoveJobFromScheduleList(taskName)
  173. //Write current job lists to file
  174. js, _ := json.Marshal(a.jobs)
  175. js = []byte(pretty.Pretty(js))
  176. ioutil.WriteFile(a.cronfile, js, 0755)
  177. sendOK(w)
  178. }
  179. func (a *Scheduler) HandleShowLog(w http.ResponseWriter, r *http.Request) {
  180. filename, _ := mv(r, "filename", false)
  181. if filename == "" {
  182. //Show index
  183. logFiles, _ := filepath.Glob(logFolder + "*.log")
  184. //Convert all to linux syntax
  185. linuxLogFiles := []string{}
  186. for _, lf := range logFiles {
  187. linuxLogFiles = append(linuxLogFiles, filepath.Base(lf))
  188. }
  189. js, _ := json.Marshal(linuxLogFiles)
  190. sendJSONResponse(w, string(js))
  191. } else {
  192. //Show log content
  193. filename = strings.ReplaceAll(filepath.ToSlash(filename), "/", "")
  194. if fileExists(filepath.Join(logFolder, filename)) {
  195. logContent, err := ioutil.ReadFile(filepath.Join(logFolder, filename))
  196. if err != nil {
  197. sendTextResponse(w, "Unable to load log file: "+filename)
  198. } else {
  199. sendTextResponse(w, string(logContent))
  200. }
  201. } else {
  202. sendTextResponse(w, "Unable to load log file: "+filename)
  203. }
  204. }
  205. }