From 27b098002287a9de09bdca6a5a32845b26606a25 Mon Sep 17 00:00:00 2001 From: trendschau Date: Sun, 17 Mar 2024 11:20:28 +0100 Subject: [PATCH] v.2.3.1 Refactore server calls in license model with curl and testcall on pageload --- .../ControllerApiSystemLicense.php | 22 ++ system/typemill/Models/License.php | 189 ++++++++++-------- system/typemill/author/js/vue-license.js | 26 +++ system/typemill/routes/api.php | 1 + system/typemill/settings/defaults.yaml | 2 +- 5 files changed, 161 insertions(+), 79 deletions(-) diff --git a/system/typemill/Controllers/ControllerApiSystemLicense.php b/system/typemill/Controllers/ControllerApiSystemLicense.php index 358f32e..63bd9ab 100644 --- a/system/typemill/Controllers/ControllerApiSystemLicense.php +++ b/system/typemill/Controllers/ControllerApiSystemLicense.php @@ -10,6 +10,28 @@ use Typemill\Static\Translations; class ControllerApiSystemLicense extends Controller { + public function testLicenseServerCall(Request $request, Response $response) + { + $license = new License(); + + $testresult = $license->testLicenseCall(); + + if(!$testresult) + { + $response->getBody()->write(json_encode([ + 'message' => $license->getMessage() + ])); + + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } + + $response->getBody()->write(json_encode([ + 'message' => Translations::translate('License server call was successful'), + ])); + + return $response->withHeader('Content-Type', 'application/json')->withStatus(200); + } + public function createLicense(Request $request, Response $response) { $params = $request->getParsedBody(); diff --git a/system/typemill/Models/License.php b/system/typemill/Models/License.php index 7adc933..86d5156 100644 --- a/system/typemill/Models/License.php +++ b/system/typemill/Models/License.php @@ -214,10 +214,26 @@ class License } } + + # THE FOLLOWING METHODS INTERACT WITH LICENSE SERVER + + public function testLicenseCall() + { + # make the call to the license server + $url = 'https://service.typemill.net/api/v1/testcall'; + $testcall = $this->callLicenseServer(['test' => 'test'], $url); + + if(!$testcall) + { + return false; + } + + return true; + } + public function activateLicense($params) { # prepare data for call to licence server - $readableMail = trim($params['email']); $licensedata = [ @@ -226,44 +242,12 @@ class License 'domain' => $params['domain'] ]; - $postdata = http_build_query($licensedata); + # make the call to the license server + $url = 'https://service.typemill.net/api/v1/activate'; + $signedLicense = $this->callLicenseServer($licensedata, $url); - $authstring = $this->getPublicKeyPem(); - $authstring = hash('sha256', substr($authstring, 0, 50)); - - $options = array ( - 'http' => array ( - 'method' => 'POST', - 'ignore_errors' => true, - 'header' => "Content-Type: application/x-www-form-urlencoded\r\n" . - "Accept: application/json\r\n" . - "Authorization: $authstring\r\n" . - "Connection: close\r\n", - 'content' => $postdata - ) - ); - - $context = stream_context_create($options); - - $response = file_get_contents('https://service.typemill.net/api/v1/activate', false, $context); - - $signedLicense = json_decode($response,true); - - if(substr($http_response_header[0], -6) != "200 OK") + if(!$signedLicense) { - $message = $http_response_header[0]; - if(isset($signedLicense['code']) && ($signedLicense['code'] != '')) - { - $message = $signedLicense['code']; - } - $this->message = Translations::translate('Answer from license server: ') . $message; - - return false; - } - - if(isset($signedLicense['code'])) - { - $this->message = $signedLicense['code']; return false; } @@ -295,48 +279,12 @@ class License 'payed_until' => $data['payed_until'] ]; - $postdata = http_build_query($licensedata); + # make the call to the license server + $url = 'https://service.typemill.net/api/v1/update'; + $signedLicense = $this->callLicenseServer($licensedata, $url); - $authstring = $this->getPublicKeyPem(); - $authstring = hash('sha256', substr($authstring, 0, 50)); - - $options = array ( - 'http' => array ( - 'method' => 'POST', - 'ignore_errors' => true, - 'header' => "Content-Type: application/x-www-form-urlencoded\r\n" . - "Accept: application/json\r\n" . - "Authorization: $authstring\r\n" . - "Connection: close\r\n", - 'content' => $postdata - ) - ); - - $context = stream_context_create($options); - - $response = file_get_contents('https://service.typemill.net/api/v1/update', false, $context); - - $signedLicense = json_decode($response,true); - - if(substr($http_response_header[0], -6) != "200 OK") + if(!$signedLicense) { - $message = $http_response_header[0]; - - if(isset($signedLicense['code']) && ($signedLicense['code'] != '')) - { - $message = $signedLicense['code']; - } - - # problem: if admin is on license website, then the first check has already been done on start in system and it has set timer, so the admin will never see this message from server. - $this->message = Translations::translate('Answer from license server: ') . $message; - - return false; - } - - if(isset($signedLicense['code'])) - { - $this->message = $signedLicense['code']; - return false; } @@ -355,12 +303,97 @@ class License return true; } + private function callLicenseServer( $licensedata, $url ) + { + $authstring = $this->getPublicKeyPem(); + + if(!$authstring) + { + $this->message = Translations::translate('Please check if there is a readable file public_key.pem in your settings folder.'); + + return false; + } + + $authstring = hash('sha256', substr($authstring, 0, 50)); + + $postdata = http_build_query($licensedata); + + if(in_array('curl', get_loaded_extensions())) + { + $curl = curl_init($url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $postdata); + curl_setopt($curl, CURLOPT_HTTPHEADER, array( + "Content-Type: application/x-www-form-urlencoded", + "Accept: application/json", + "Authorization: $authstring", + "Connection: close" + )); + + $response = curl_exec($curl); + + if (curl_errno($curl)) + { + $this->message = Translations::translate('We got a curl error: ') . curl_error($curl); + + return false; + } + + curl_close($curl); + } + else + { + $options = array ( + 'http' => array ( + 'method' => 'POST', + 'ignore_errors' => true, + 'header' => "Content-Type: application/x-www-form-urlencoded\r\n" . + "Accept: application/json\r\n" . + "Authorization: $authstring\r\n" . + "Connection: close\r\n", + 'content' => $postdata + ) + ); + + $context = stream_context_create($options); + + $response = file_get_contents($url, false, $context); + + if ($response === FALSE) + { + if (!empty($http_response_header)) + { + list($version, $status_code, $msg) = explode(' ', $http_response_header[0], 3); + + $this->message = Translations::translate('We got an error from file_get_contents: ') . $status_code . ' ' . $msg; + } + else + { + $this->message = Translations::translate('No HTTP response received or file_get_contents is blocked.'); + } + + return false; + } + } + + $responseJson = json_decode($response,true); + + if(isset($responseJson['code'])) + { + $this->message = $responseJson['code']; + + return false; + } + + return $responseJson; + } + private function hashMail(string $mail) { return hash('sha256', trim($mail) . 'TYla5xa8JUur'); } - # we have it in static license, too so use it from static and delete this duplicate. public function getPublicKeyPem() { $pkeyfile = getcwd() . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . "public_key.pem"; diff --git a/system/typemill/author/js/vue-license.js b/system/typemill/author/js/vue-license.js index 172480d..6270e2b 100644 --- a/system/typemill/author/js/vue-license.js +++ b/system/typemill/author/js/vue-license.js @@ -93,6 +93,32 @@ const app = Vue.createApp({ eventBus.$on('forminput', formdata => { this.formData[formdata.name] = formdata.value; }); + + /* test if the license server is reachable and all settings are ok */ + this.disabled = true; + var self = this; + + tmaxios.post('/api/v1/licensetestcall',{ + 'license': 'test' + }) + .then(function (response) + { + self.disabled = false; + }) + .catch(function (error) + { + if(error.response) + { + self.disabled = false; + self.message = handleErrorMessage(error); + self.messageClass = 'bg-rose-500'; + self.licensemessage = error.response.data.message; + if(error.response.data.errors !== undefined) + { + self.errors = error.response.data.errors; + } + } + }); }, methods: { selectComponent: function(type) diff --git a/system/typemill/routes/api.php b/system/typemill/routes/api.php index ffa1648..21734ec 100644 --- a/system/typemill/routes/api.php +++ b/system/typemill/routes/api.php @@ -31,6 +31,7 @@ $app->group('/api/v1', function (RouteCollectorProxy $group) use ($acl) { $group->get('/settings', ControllerApiSystemSettings::class . ':getSettings')->setName('api.settings.get')->add(new ApiAuthorization($acl, 'system', 'view')); # admin $group->post('/settings', ControllerApiSystemSettings::class . ':updateSettings')->setName('api.settings.set')->add(new ApiAuthorization($acl, 'system', 'update')); # admin $group->post('/license', ControllerApiSystemLicense::class . ':createLicense')->setName('api.license.create')->add(new ApiAuthorization($acl, 'system', 'update')); # admin + $group->post('/licensetestcall', ControllerApiSystemLicense::class . ':testLicenseServerCall')->setName('api.license.testcall')->add(new ApiAuthorization($acl, 'system', 'update')); # admin $group->post('/themecss', ControllerApiSystemThemes::class . ':updateThemeCss')->setName('api.themecss.set')->add(new ApiAuthorization($acl, 'system', 'update')); # admin $group->post('/theme', ControllerApiSystemThemes::class . ':updateTheme')->setName('api.theme.set')->add(new ApiAuthorization($acl, 'system', 'update')); # admin $group->post('/plugin', ControllerApiSystemPlugins::class . ':updatePlugin')->setName('api.plugin.set')->add(new ApiAuthorization($acl, 'system', 'update')); # admin diff --git a/system/typemill/settings/defaults.yaml b/system/typemill/settings/defaults.yaml index ee85890..6b1eb1f 100644 --- a/system/typemill/settings/defaults.yaml +++ b/system/typemill/settings/defaults.yaml @@ -1,4 +1,4 @@ -version: '2.3.0' +version: '2.3.1' title: 'Typemill' author: 'Unknown' copyright: false