From eff3429f4309e262b891af0916dd40be323a43c1 Mon Sep 17 00:00:00 2001 From: Jeroen De Meerleer Date: Tue, 13 Apr 2021 14:44:58 +0200 Subject: [PATCH] Added input fields for secrets --- lib/Framework/Router.php | 2 +- public/resources/job/add.css | 2 +- public/resources/job/add.js | 13 +++++++++-- src/Controller/JobController.php | 3 ++- src/Repository/Job.php | 22 ++++++++++++++++++ src/Repository/Secret.php | 33 +++++++++++++++++++++++++++ src/Repository/User.php | 26 +++++++--------------- templates/job/add.html.twig | 38 ++++++++++++++++++++++++++++---- 8 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 src/Repository/Secret.php diff --git a/lib/Framework/Router.php b/lib/Framework/Router.php index 7704d90..a108684 100644 --- a/lib/Framework/Router.php +++ b/lib/Framework/Router.php @@ -4,8 +4,8 @@ namespace JeroenED\Framework; -use http\Exception\InvalidArgumentException; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Filesystem\Exception\InvalidArgumentException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Generator\UrlGenerator; diff --git a/public/resources/job/add.css b/public/resources/job/add.css index 8d1f9da..226db6c 100644 --- a/public/resources/job/add.css +++ b/public/resources/job/add.css @@ -1,3 +1,3 @@ -.crontype-inputs { +.hidden { display: none; } \ No newline at end of file diff --git a/public/resources/job/add.js b/public/resources/job/add.js index 2e679ea..db2fe83 100644 --- a/public/resources/job/add.js +++ b/public/resources/job/add.js @@ -1,6 +1,7 @@ $(function() { initDatePickers(); initCronType(); + initSecretInputs(); }); function initDatePickers() @@ -14,7 +15,15 @@ function initCronType() $('.crontype-item').on('click', function() { let type = $(this).data('type'); $('.crontype').val(type); - $('.crontype-inputs').hide(); - $('.crontype-' + type).show(); + $('.crontype-inputs:not(.hidden)').addClass('hidden'); + $('.crontype-' + type).removeClass('hidden'); + }) +} + +function initSecretInputs() +{ + $('.addsecret-btn').on('click', function() { + $('.secret-group:first-child').clone().appendTo('.secrets').removeClass('hidden'); + $('.secrets-description').removeClass('hidden'); }) } \ No newline at end of file diff --git a/src/Controller/JobController.php b/src/Controller/JobController.php index 45bfc2e..d88dc15 100644 --- a/src/Controller/JobController.php +++ b/src/Controller/JobController.php @@ -22,7 +22,8 @@ class JobController extends Controller public function viewAction($id) { - return new Response('Not implemented yet', Response::HTTP_TOO_EARLY); + $jobRepo = new Job($this->getDbCon()); + $job = $jobRepo->getJob($id); } public function addAction() diff --git a/src/Repository/Job.php b/src/Repository/Job.php index 1294782..83c5725 100644 --- a/src/Repository/Job.php +++ b/src/Repository/Job.php @@ -52,6 +52,7 @@ class Job case 'http': $parsedUrl = parse_url($values['url']); $data['url'] = $values['url']; + $data['basicauth-username'] = $values['basicauth-username']; if(empty($parsedUrl['host'])) { return ['success' => false, 'message' => 'Some data was invalid']; } @@ -59,6 +60,12 @@ class Job break; } + if(!empty($values['secretval'])) { + foreach($values['secretval'] as $key => $name) { + if(!empty($name)) $data['secrets'][$values['secretid'][$key]] = base64_encode(Secret::encrypt($values['secretval'][$key])); + } + } + $data = json_encode($data); $addJobSql = "INSERT INTO job(name, data, delay, nextrun, lastrun) VALUES (:name, :data, :delay, :nextrun, :lastrun)"; @@ -67,4 +74,19 @@ class Job return ['success' => true, 'message' => 'Cronjob succesfully added']; } + + public function getJob(int $id, bool $withSecrets = false) { + $jobSql = "SELECT * FROM job WHERE id = :id"; + $jobStmt = $this->dbcon->prepare($jobSql); + $jobRslt = $jobStmt->execute([':id' => $id])->fetchAssociative(); + + $jobRslt['data'] = json_decode($jobRslt['data'], true); + if(!empty($jobRslt['data']['secrets'])) { + foreach ($jobRslt['data']['secrets'] as $key => &$value) { + $value = ($withSecrets) ? Secret::decrypt(base64_decode($value)) : ''; + } + } + + return $jobRslt; + } } \ No newline at end of file diff --git a/src/Repository/Secret.php b/src/Repository/Secret.php new file mode 100644 index 0000000..8c9d229 --- /dev/null +++ b/src/Repository/Secret.php @@ -0,0 +1,33 @@ + $time, 'password' => base64_encode($iv . $hash . $ciphertext)])); + $password = substr($time, -7) . $password; + $encrypted = Secret::encrypt($password); + return base64_encode(json_encode(['time' => $time, 'password' => base64_encode($encrypted)])); } public function getPassFromAutologinToken($token) { $extracted = json_decode(base64_decode($token), true); - $method = $_ENV['ENCRYPTION_METHOD']; $encrypted = base64_decode($extracted['password']); - $iv = substr($encrypted, 0, 16); - $hash = substr($encrypted, 16, 32); - $ciphertext = substr($encrypted, 48); - $key = hash($_ENV['HASHING_METHOD'], $_ENV['SECRET'], true); - if (!hash_equals(hash_hmac($_ENV['HASHING_METHOD'], $ciphertext . $iv, $key, true), $hash)) return null; - - $decryption = openssl_decrypt($ciphertext, $method, $key, OPENSSL_RAW_DATA, $iv); + $decrypted = Secret::decrypt($encrypted); return ( (($extracted['time'] + $_ENV['COOKIE_LIFETIME']) > time()) && - substr($extracted['time'], -7) == substr($decryption, -7) + substr($extracted['time'], -7) == substr($decrypted, -7) ) - ? substr($decryption, 0, -7) : null; + ? substr($decrypted, 0, -7) : null; } } \ No newline at end of file diff --git a/templates/job/add.html.twig b/templates/job/add.html.twig index 342cd9f..c8a5414 100644 --- a/templates/job/add.html.twig +++ b/templates/job/add.html.twig @@ -4,6 +4,7 @@

Add a cronjob

+

General info

@@ -14,16 +15,18 @@
- +
- +
+ +

Job details

-
+ + +

Secrets

+
+ +
+ + +