From 4cf6c649b604a9ad30d1cdbaa73f8420b1f30028 Mon Sep 17 00:00:00 2001 From: Jeroen De Meerleer Date: Fri, 21 May 2021 13:09:48 +0200 Subject: [PATCH] NEW FEATURE: editing jobs --- config/routes.yaml | 7 + public/resources/job/add.js | 4 +- public/resources/job/index.css | 3 - src/Controller/JobController.php | 34 ++++- src/Repository/Job.php | 116 +++++++++----- templates/base.html.twig | 6 +- templates/job/add.html.twig | 7 +- templates/job/edit.html.twig | 253 +++++++++++++++++++++++++++++++ templates/job/index.html.twig | 82 +++++----- 9 files changed, 416 insertions(+), 96 deletions(-) create mode 100644 templates/job/edit.html.twig diff --git a/config/routes.yaml b/config/routes.yaml index 1b65b8b..d0891ce 100644 --- a/config/routes.yaml +++ b/config/routes.yaml @@ -31,6 +31,13 @@ job_view: requirements: id: \d+ +job_edit: + path: '/job/{id}/edit' + defaults: + _controller: JeroenED\Webcron\Controller\JobController::editAction + requirements: + id: \d+ + job_add: path: '/job/add' defaults: diff --git a/public/resources/job/add.js b/public/resources/job/add.js index 60dab5f..c605f94 100644 --- a/public/resources/job/add.js +++ b/public/resources/job/add.js @@ -10,8 +10,8 @@ $(function() { function initDatePickers() { - $('#nextrunselector').datetimepicker({format: 'L LTS'}); - $('#lastrunselector').datetimepicker({format: 'L LTS'}); + $('#nextrunselector').datetimepicker({format: 'DD/MM/YYYY HH:mm:ss'}); + $('#lastrunselector').datetimepicker({format: 'DD/MM/YYYY HH:mm:ss'}); } function initCronType() diff --git a/public/resources/job/index.css b/public/resources/job/index.css index 85d92c6..e69de29 100644 --- a/public/resources/job/index.css +++ b/public/resources/job/index.css @@ -1,3 +0,0 @@ -.text-end { - text-align: right; -} \ No newline at end of file diff --git a/src/Controller/JobController.php b/src/Controller/JobController.php index d88dc15..b685c21 100644 --- a/src/Controller/JobController.php +++ b/src/Controller/JobController.php @@ -26,6 +26,27 @@ class JobController extends Controller $job = $jobRepo->getJob($id); } + public function editAction($id) + { + if($this->getRequest()->getMethod() == 'GET') { + $jobRepo = new Job($this->getDbCon()); + $job = $jobRepo->getJob($id, true); + return $this->render('job/edit.html.twig', $job); + } elseif($this->getRequest()->getMethod() == 'POST') { + $allValues = $this->getRequest()->request->all(); + $jobRepo = new Job($this->getDbCon()); + + try { + $joboutput = $jobRepo->editJob($id, $allValues); + } catch (\InvalidArgumentException $e) { + $this->addFlash('danger', $e->getMessage()); + return new RedirectResponse($this->generateRoute('job_edit', ['id' => $allValues['id']])); + } + $this->addFlash('success', $joboutput['message']); + return new RedirectResponse($this->generateRoute('job_index')); + } + } + public function addAction() { if($this->getRequest()->getMethod() == 'GET') { @@ -33,14 +54,15 @@ class JobController extends Controller } elseif ($this->getRequest()->getMethod() == 'POST') { $allValues = $this->getRequest()->request->all(); $jobRepo = new Job($this->getDbCon()); - $joboutput = $jobRepo->addJob($allValues); - if($joboutput['success']) { - $this->addFlash('success', $joboutput['message']); - return new RedirectResponse($this->generateRoute('job_index')); - } else { - $this->addFlash('danger', $joboutput['message']); + try { + $joboutput = $jobRepo->addJob($allValues); + } catch (\InvalidArgumentException $e) { + $this->addFlash('danger', $e->getMessage()); return new RedirectResponse($this->generateRoute('job_add')); } + $this->addFlash('success', $joboutput['message']); + return new RedirectResponse($this->generateRoute('job_index')); + } else { return new Response('Not implemented yet', Response::HTTP_TOO_EARLY); } diff --git a/src/Repository/Job.php b/src/Repository/Job.php index 10ca80c..f7f429e 100644 --- a/src/Repository/Job.php +++ b/src/Repository/Job.php @@ -35,30 +35,62 @@ class Job empty($values['interval']) || empty($values['nextrun']) ) { - return ['success' => false, 'message' => 'Some fields are empty']; + throw new \InvalidArgumentException('Some fields are empty'); } + $data = $this->prepareJob($values); + $data['data'] = json_encode($data['data']); + $addJobSql = "INSERT INTO job(name, data, interval, nextrun, lastrun) VALUES (:name, :data, :interval, :nextrun, :lastrun)"; + + $addJobStmt = $this->dbcon->prepare($addJobSql); + $addJobStmt->executeQuery([':name' => $data['name'], ':data' => $data['data'], ':interval' => $data['interval'], ':nextrun' => $data['nextrun'], ':lastrun' => $data['lastrun'], ]); + + return ['success' => true, 'message' => 'Cronjob succesfully added']; + } + + public function editJob(int $id, array $values) + { + if(empty($values['crontype']) || + empty($values['name']) || + empty($values['interval']) || + empty($values['nextrun']) + ) { + throw new \InvalidArgumentException('Some fields are empty'); + } + + $data = $this->prepareJob($values); + $data['data'] = json_encode($data['data']); + $editJobSql = "UPDATE job set name = :name, data = :data, interval = :interval, nextrun = :nextrun, lastrun = :lastrun WHERE id = :id"; + + $editJobStmt = $this->dbcon->prepare($editJobSql); + $editJobStmt->executeQuery([':name' => $data['name'], ':data' => $data['data'], ':interval' => $data['interval'], ':nextrun' => $data['nextrun'], ':lastrun' => $data['lastrun'],':id' => $id ]); + + return ['success' => true, 'message' => 'Cronjob succesfully edited']; + } + + public function prepareJob(array $values): array + { if(empty($values['lastrun'])) { $values['lastrun'] = NULL; } else { - $values['lastrun'] = DateTime::createFromFormat('m/d/Y g:i:s A',$values['lastrun'])->getTimestamp(); + $values['lastrun'] = DateTime::createFromFormat('m/d/Y H:i:s',$values['lastrun'])->getTimestamp(); } - $values['nextrun'] = DateTime::createFromFormat('m/d/Y g:i:s A', $values['nextrun'])->getTimestamp(); - $data['crontype'] = $values['crontype']; - $data['hosttype'] = $values['hosttype']; - $data['containertype'] = $values['containertype']; + $values['nextrun'] = DateTime::createFromFormat('m/d/Y H:i:s', $values['nextrun'])->getTimestamp(); + $values['data']['crontype'] = $values['crontype']; + $values['data']['hosttype'] = $values['hosttype']; + $values['data']['containertype'] = $values['containertype']; - switch($data['crontype']) + switch($values['data']['crontype']) { case 'command': - $data['command'] = $values['command']; - $data['response'] = $values['response']; + $values['data']['command'] = $values['command']; + $values['data']['response'] = $values['response']; break; case 'reboot': - $data['reboot-command'] = $values['reboot-command']; - $data['getservices-command'] = $values['getservices-command']; - $data['reboot-duration'] = $values['reboot-duration']; + $values['data']['reboot-command'] = $values['reboot-command']; + $values['data']['getservices-command'] = $values['getservices-command']; + $values['data']['reboot-duration'] = $values['reboot-duration']; if(!empty($values['reboot-delay'])) { $newsecretkey = count($values['var-value']); $values['var-id'][$newsecretkey] = 'reboot-delay'; @@ -73,11 +105,11 @@ class Job break; case 'http': $parsedUrl = parse_url($values['url']); - $data['url'] = $values['url']; - $data['response'] = $values['response']; - $data['basicauth-username'] = $values['basicauth-username']; + $values['data']['url'] = $values['url']; + $values['data']['response'] = $values['response']; + $values['data']['basicauth-username'] = $values['basicauth-username']; if(empty($parsedUrl['host'])) { - return ['success' => false, 'message' => 'Some data was invalid']; + throw new \InvalidArgumentException('Some data was invalid'); } if(!empty($values['basicauth-password'])) { $newsecretkey = count($values['var-value']); @@ -85,22 +117,22 @@ class Job $values['var-issecret'][$newsecretkey] = true; $values['var-value'][$newsecretkey] = $values['basicauth-password']; } - $data['host'] = $parsedUrl['host']; + $values['data']['host'] = $parsedUrl['host']; break; } - switch($data['hosttype']) { + switch($values['data']['hosttype']) { case 'local': - $data['host'] = 'localhost'; + $values['data']['host'] = 'localhost'; break; case 'ssh': - $data['host'] = $values['host']; - $data['user'] = $values['user']; + $values['data']['host'] = $values['host']; + $values['data']['user'] = $values['user']; if(!empty($values['privkey-password'])) { - $newsecretkey = count($values['var-value']); - $values['var-id'][$newsecretkey] = 'privkey-password'; - $values['var-issecret'][$newsecretkey] = true; - $values['var-value'][$newsecretkey] = $values['privkey-password']; + $newsecretkey = count($values['var-value']); + $values['var-id'][$newsecretkey] = 'privkey-password'; + $values['var-issecret'][$newsecretkey] = true; + $values['var-value'][$newsecretkey] = $values['privkey-password']; } if(!empty($_FILES['privkey']['tmp_name'])) { $newsecretkey = count($values['var-value']); @@ -112,10 +144,10 @@ class Job } - switch($data['containertype']) { + switch($values['data']['containertype']) { case 'docker': - $data['service'] = $values['service']; - $data['user'] = $values['user']; + $values['data']['service'] = $values['service']; + $values['data']['user'] = $values['user']; break; } @@ -123,23 +155,16 @@ class Job foreach($values['var-value'] as $key => $name) { if(!empty($name)) { if(isset($values['var-issecret'][$key]) && $values['var-issecret'][$key] != false) { - $data['vars'][$values['var-id'][$key]]['issecret'] = true; - $data['vars'][$values['var-id'][$key]]['value'] = base64_encode(Secret::encrypt($values['var-value'][$key])); + $values['data']['vars'][$values['var-id'][$key]]['issecret'] = true; + $values['data']['vars'][$values['var-id'][$key]]['value'] = base64_encode(Secret::encrypt($values['var-value'][$key])); } else { - $data['vars'][$values['var-id'][$key]]['issecret'] = false; - $data['vars'][$values['var-id'][$key]]['value'] = $values['var-value'][$key]; + $values['data']['vars'][$values['var-id'][$key]]['issecret'] = false; + $values['data']['vars'][$values['var-id'][$key]]['value'] = $values['var-value'][$key]; } } } } - - $data = json_encode($data); - $addJobSql = "INSERT INTO job(name, data, interval, nextrun, lastrun) VALUES (:name, :data, :interval, :nextrun, :lastrun)"; - - $addJobStmt = $this->dbcon->prepare($addJobSql); - $addJobStmt->executeQuery([':name' => $values['name'], ':data' => $data, ':interval' => $values['interval'], ':nextrun' => $values['nextrun'], ':lastrun' => $values['lastrun'], ]); - - return ['success' => true, 'message' => 'Cronjob succesfully added']; + return $values; } public function getJob(int $id, bool $withSecrets = false) { @@ -148,6 +173,7 @@ class Job $jobRslt = $jobStmt->execute([':id' => $id])->fetchAssociative(); $jobRslt['data'] = json_decode($jobRslt['data'], true); + if(!empty($jobRslt['data']['vars'])) { foreach ($jobRslt['data']['vars'] as $key => &$value) { if ($value['issecret']) { @@ -156,6 +182,16 @@ class Job } } + switch($jobRslt['data']['crontype']) { + case 'http': + if(isset($jobRslt['data']['vars']['basicauth-password']['value'])) { + $jobRslt['data']['basicauth-password'] = $jobRslt['data']['vars']['basicauth-password']['value']; + unset($jobRslt['data']['vars']['basicauth-password']); + } + break; + } + if($jobRslt['data']['crontype'] == 'http') { + } return $jobRslt; } } \ No newline at end of file diff --git a/templates/base.html.twig b/templates/base.html.twig index e0457a5..890f3d8 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -18,14 +18,14 @@
-
+
-
+
-
+
{{ include('flashes.html.twig') }} {% block content %}{% endblock %}
diff --git a/templates/job/add.html.twig b/templates/job/add.html.twig index 236316f..e91ec98 100644 --- a/templates/job/add.html.twig +++ b/templates/job/add.html.twig @@ -39,7 +39,7 @@

Job details