handlers.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package aecron
  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 *Aecron) 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, _ := json.Marshal(userCreatedJobs)
  43. sendJSONResponse(w, string(js))
  44. }
  45. func (a *Aecron) 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. realScriptPath, err := userinfo.VirtualPathToRealPath(scriptpath)
  77. if err != nil {
  78. sendErrorResponse(w, err.Error())
  79. return
  80. }
  81. //Check if the user has permission to create this script
  82. if filepath.Ext(realScriptPath) != ".js" && filepath.Ext(realScriptPath) != ".agi" {
  83. //Require admin permission
  84. if userinfo.IsAdmin() == false {
  85. sendErrorResponse(w, "Admin permission required for scheduling non AGI script")
  86. return
  87. }
  88. }
  89. interval := int64(86400) //default 1 day in seconds
  90. intervalString, err := mv(r, "interval", true)
  91. if err != nil {
  92. //Default 1 day
  93. } else {
  94. //Parse the intervalString into int
  95. intervalInt, err := strconv.ParseInt(intervalString, 10, 64)
  96. if err != nil {
  97. //Failed to parse interval to int
  98. sendErrorResponse(w, "Invalid interval")
  99. return
  100. }
  101. interval = intervalInt
  102. }
  103. baseUnixTime := time.Now().Unix()
  104. baseTimeString, err := mv(r, "base", true)
  105. if err != nil {
  106. //Use curent timestamp as base
  107. } else {
  108. baseTimeInt, err := strconv.Atoi(baseTimeString)
  109. if err != nil {
  110. //Failed to parse interval to int
  111. sendErrorResponse(w, "Invalid Base Time")
  112. return
  113. }
  114. baseUnixTime = int64(baseTimeInt)
  115. }
  116. //Create a new job
  117. newJob := Job{
  118. Name: taskName,
  119. Creator: userinfo.Username,
  120. Admin: userinfo.IsAdmin(),
  121. Description: jobDescription,
  122. ExecutionInterval: int64(interval),
  123. BaseTime: baseUnixTime,
  124. ScriptFile: realScriptPath,
  125. }
  126. //Write current job lists to file
  127. a.jobs = append(a.jobs, &newJob)
  128. js, _ := json.Marshal(a.jobs)
  129. js = []byte(pretty.Pretty(js))
  130. ioutil.WriteFile(a.cronfile, js, 0755)
  131. //OK
  132. sendOK(w)
  133. }
  134. func (a *Aecron) HandleJobRemoval(w http.ResponseWriter, r *http.Request) {
  135. userinfo, err := a.userHandler.GetUserInfoFromRequest(w, r)
  136. if err != nil {
  137. sendErrorResponse(w, "User not logged in")
  138. return
  139. }
  140. //Get required paramaters
  141. taskName, err := mv(r, "name", true)
  142. if err != nil {
  143. sendErrorResponse(w, "Invalid task name")
  144. return
  145. }
  146. //Check if Job exists
  147. if !a.JobExists(taskName) {
  148. //Job with that name not exists
  149. sendErrorResponse(w, "Job not exists")
  150. return
  151. }
  152. targetJob := a.GetScheduledJobByName(taskName)
  153. //Job exists. Check if the job is created by the user.
  154. //User can only remove job created by himself or all job is he is admin
  155. allowRemove := false
  156. if userinfo.IsAdmin() == false && targetJob.Creator == userinfo.Username {
  157. allowRemove = true
  158. } else if userinfo.IsAdmin() == true {
  159. allowRemove = true
  160. }
  161. if !allowRemove {
  162. sendErrorResponse(w, "Permission Denied")
  163. return
  164. }
  165. //Ok. Remove Job from the list
  166. a.RemoveJobFromScheduleList(taskName)
  167. //Write current job lists to file
  168. js, _ := json.Marshal(a.jobs)
  169. js = []byte(pretty.Pretty(js))
  170. ioutil.WriteFile(a.cronfile, js, 0755)
  171. sendOK(w)
  172. }
  173. func (a *Aecron) HandleShowLog(w http.ResponseWriter, r *http.Request) {
  174. filename, _ := mv(r, "filename", false)
  175. if filename == "" {
  176. //Show index
  177. logFiles, _ := filepath.Glob(logFolder + "*.log")
  178. //Convert all to linux syntax
  179. linuxLogFiles := []string{}
  180. for _, lf := range logFiles {
  181. linuxLogFiles = append(linuxLogFiles, filepath.Base(lf))
  182. }
  183. js, _ := json.Marshal(linuxLogFiles)
  184. sendJSONResponse(w, string(js))
  185. } else {
  186. //Show log content
  187. filename = strings.ReplaceAll(filepath.ToSlash(filename), "/", "")
  188. if fileExists(filepath.Join(logFolder, filename)) {
  189. logContent, err := ioutil.ReadFile(filepath.Join(logFolder, filename))
  190. if err != nil {
  191. sendTextResponse(w, "Unable to load log file: "+filename)
  192. } else {
  193. sendTextResponse(w, string(logContent))
  194. }
  195. } else {
  196. sendTextResponse(w, "Unable to load log file: "+filename)
  197. }
  198. }
  199. }