From 7b51d55468c054326a4d6b98bb1841b6c650eca2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dicky=20Herlambang=20=28=E8=8A=B1=EF=BC=89?= Date: Mon, 20 May 2024 07:38:51 +0700 Subject: [PATCH] Controllers: Introduce versioning controller - Introduce controller to fetch and validate latest version on git and version that send and exist on client version. If version are not match, then return error to notify user clear cache their browser manually --- app/Helpers/NotificationHelper.php | 136 ++++++ .../Controllers/Api/versionController.php | 457 ++++++++++++++++++ app/Http/Controllers/Controller.php | 22 + routes/api.php | 7 + 4 files changed, 622 insertions(+) create mode 100644 app/Http/Controllers/Api/versionController.php diff --git a/app/Helpers/NotificationHelper.php b/app/Helpers/NotificationHelper.php index 6f5d0b14..2b54e055 100644 --- a/app/Helpers/NotificationHelper.php +++ b/app/Helpers/NotificationHelper.php @@ -338,4 +338,140 @@ function sendDailyTaskNotify($compTotalScs, $compTotalErr, $cnvTotalScs, $cnvTot } } } + + function sendErrGlobalNotify($processEndpoint, $processName, $processId , $status, $errReason, $errCode) { + $CurrentTime = AppHelper::instance()->getCurrentTimeZone(); + $message = "HANA API Alert + \nStatus: ".$status."". + "\nStart At: ".$CurrentTime. + "\nEnvironment: ".env('APP_ENV'). + "\n\nServices: Backend Services". + "\nSource: https://gw.hana-ci.com". + "\nEndpoint: ".$processEndpoint. + "\n\nProcess: ".$processName. + "\nProcess Id: ".$processId. + "\nType: Universal Notifyr". + "\n\nError Reason: ".$errReason. + "\nError Log:
".$errCode.
+                    "
"; + try { + $response = Telegram::sendMessage([ + 'chat_id' => env('TELEGRAM_CHAT_ID'), + 'text' => $message, + 'parse_mode' => 'HTML' + ]); + $messageId = $response->getMessageId(); + + try { + DB::table('notifyLogs')->insert([ + 'processId' => $processId, + 'notifyName' => 'Telegram SDK', + 'notifyResult' => true, + 'notifyMessage' => 'Message has been sent !', + 'notifyResponse' => $response + ]); + } catch (QueryException $ex) { + Log::error('Query Exception failed with: '. $ex->getMessage()); + } + } catch (\Telegram\Bot\Exceptions\TelegramResponseException $e) { + try { + if ($e->getHttpStatusCode() == null) { + $httpStatus = null; + } else { + $httpStatus = $e->getHttpStatusCode(); + } + DB::table('notifyLogs')->insert([ + 'processId' => $processId, + 'notifyName' => 'Telegram SDK', + 'notifyResult' => false, + 'notifyMessage' => 'TelegramResponseException', + 'notifyResponse' => $e->getMessage()+' | '+$httpStatus+' | '+$e->getErrorType() + ]); + } catch (QueryException $ex) { + Log::error('Query Exception failed with: '. $ex->getMessage()); + } + } catch (\Exception $e) { + try { + DB::table('notifyLogs')->insert([ + 'processId' => $processId, + 'notifyName' => 'Telegram SDK', + 'notifyResult' => false, + 'notifyMessage' => 'Unexpected handling exception !', + 'notifyResponse' => $e->getMessage() + ]); + } catch (QueryException $ex) { + Log::error('Query Exception failed with: '. $ex->getMessage()); + } + } + } + + function sendVersioningErrNotify($versioningFE, $versioningGitFE, $versioningBE , $versioningGitBE, $status, $processId, $errReason, $errCode) { + $CurrentTime = AppHelper::instance()->getCurrentTimeZone(); + $message = "HANA API Alert + \nStatus: ".$status."". + "\nStart At: ".$CurrentTime. + "\nEnvironment: ".env('APP_ENV'). + "\n\nServices: Backend Services". + "\nSource: https://gw.hana-ci.com". + "\nEndpoint: api/v1/version". + "\n\nProcess: Versioning". + "\nProcess Id: ".$processId. + "\nType: Versioning Check". + "\n\nBE Version: ".$versioningBE. + "\nBE Version GIT: ".$versioningGitBE. + "\nFE Version: ".$versioningFE. + "\nFE Version GIT: ".$versioningGitFE. + "\n\nError Reason: ".$errReason. + "\nError Log:
".$errCode.
+                    "
"; + try { + $response = Telegram::sendMessage([ + 'chat_id' => env('TELEGRAM_CHAT_ID'), + 'text' => $message, + 'parse_mode' => 'HTML' + ]); + $messageId = $response->getMessageId(); + + try { + DB::table('notifyLogs')->insert([ + 'processId' => $processId, + 'notifyName' => 'Telegram SDK', + 'notifyResult' => true, + 'notifyMessage' => 'Message has been sent !', + 'notifyResponse' => $response + ]); + } catch (QueryException $ex) { + Log::error('Query Exception failed with: '. $ex->getMessage()); + } + } catch (\Telegram\Bot\Exceptions\TelegramResponseException $e) { + try { + if ($e->getHttpStatusCode() == null) { + $httpStatus = null; + } else { + $httpStatus = $e->getHttpStatusCode(); + } + DB::table('notifyLogs')->insert([ + 'processId' => $processId, + 'notifyName' => 'Telegram SDK', + 'notifyResult' => false, + 'notifyMessage' => 'TelegramResponseException', + 'notifyResponse' => $e->getMessage()+' | '+$httpStatus+' | '+$e->getErrorType() + ]); + } catch (QueryException $ex) { + Log::error('Query Exception failed with: '. $ex->getMessage()); + } + } catch (\Exception $e) { + try { + DB::table('notifyLogs')->insert([ + 'processId' => $processId, + 'notifyName' => 'Telegram SDK', + 'notifyResult' => false, + 'notifyMessage' => 'Unexpected handling exception !', + 'notifyResponse' => $e->getMessage() + ]); + } catch (QueryException $ex) { + Log::error('Query Exception failed with: '. $ex->getMessage()); + } + } + } } diff --git a/app/Http/Controllers/Api/versionController.php b/app/Http/Controllers/Api/versionController.php new file mode 100644 index 00000000..8292c1eb --- /dev/null +++ b/app/Http/Controllers/Api/versionController.php @@ -0,0 +1,457 @@ +all(),[ + 'appMajorVersion' => ['required', 'numeric'], + 'appMinorVersion' => ['required', 'numeric'], + 'appPatchVersion' => ['required', 'numeric'], + 'appGitVersion' => ['required'], + 'appServicesReferrer' => ['required', 'in:FE,BE'] + ]); + + $uuid = AppHelper::Instance()->get_guid(); + + // Carbon timezone + date_default_timezone_set('Asia/Jakarta'); + $now = Carbon::now('Asia/Jakarta'); + $startProc = $now->format('Y-m-d H:i:s'); + + if ($validator->fails()) { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Validation Failed!', + 'errStatus' => $validator->messages() + ]); + NotificationHelper::Instance()->sendVersioningErrNotify(null,null,null,null,null,null, $uuid, 'FAIL','Version Check','Versioning check failed !',$validator->messages()); + return $this->returnCoreMessage( + 200, + 'Version Check Failed !', + null, + null, + 'Version Check', + $uuid, + null, + null, + null, + $validator->errors()->all() + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendVersioningErrNotify(null,null,null,null,null,null, $uuid, 'FAIL','Version Check','Database connection error !',$ex->getMessage()); + return $this->returnCoreMessage( + 200, + 'Database connection error !', + null, + null, + 'Version Check', + $uuid, + null, + null, + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendVersioningErrNotify(null,null,null,null,null, null, $uuid, 'FAIL','Version Check','Eloquent transaction error !', $e->getMessage()); + return $this->returnCoreMessage( + 200, + 'Eloquent transaction error !', + null, + null, + 'Version Check', + $uuid, + null, + null, + null, + $e->getMessage() + ); + } + } else { + $appMajorVersionFE = $request->post('appMajorVersion'); + $appMinorVersionFE = $request->post('appMinorVersion'); + $appPatchVersionFE = $request->post('appPatchVersion'); + $appGitVersionFE = $request->post('appGitVersion'); + $appServicesReferrerFE = $request->post('appServicesReferrer'); + $appMajorVersionBE = 3; + $appMinorVersionBE = 2; + $appPatchVersionBE = 5; + $appGitVersionBE = trim(exec('git log --pretty="%h" -n1 HEAD')); + $appServicesReferrerBE = "BE"; + $validateBE = false; + $validateFE = false; + $validateMessage = ''; + $url = 'https://raw.githubusercontent.com/Nicklas373/Hana-PDF/versioning/versioning.json'; + + if (appHelper::instance()->checkWebAvailable($url)) { + $response = Http::get($url); + if ($response->successful()) { + $data = $response->json(); + try { + foreach ($data as $service) { + if ($service['appServices'] === 'BE') { + $majorVersionBE = $service['versioning']['majorVersion']; + $minorVersionBE = $service['versioning']['minorVersion']; + $patchVersionBE = $service['versioning']['patchVersion']; + $gitRevisionBE = $service['versioning']['gitRevision']; + $appVersioningBE = $appMajorVersionBE.'.'.$appMinorVersionBE.'.'.$appPatchVersionBE.'-'.$appGitVersionBE; + $versioningBE = $majorVersionBE.'.'.$minorVersionBE.'.'.$patchVersionBE.'-'.$gitRevisionBE; + } else if ($service['appServices'] === 'FE') { + $majorVersionFE = $service['versioning']['majorVersion']; + $minorVersionFE = $service['versioning']['minorVersion']; + $patchVersionFE = $service['versioning']['patchVersion']; + $gitRevisionFE = $service['versioning']['gitRevision']; + $appVersioningFE = $appMajorVersionFE.'.'.$appMinorVersionFE.'.'.$appPatchVersionFE.'-'.$appGitVersionFE; + $versioningFE = $majorVersionFE.'.'.$minorVersionFE.'.'.$patchVersionFE.'-'.$gitRevisionFE; + } + } + + if ($appVersioningBE == $versioningBE) { + $validateBE = true; + if ($appVersioningFE == $versioningFE) { + $validateFE = true; + } else { + $validateFE = false; + $validateMessage = 'Front-End module version missmatch !'; + } + } else { + $validateBE = false; + $validateFE = false; + $validateMessage = 'Back-End module version missmatch !'; + } + + if ($validateBE && $validateFE) { + return $this->returnVersioningMessage( + 200, + 'OK', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + null + ); + } else { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Version Check Failed !', + 'errStatus' => $validateMessage + ]); + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, $versioningFE, $appVersioningBE, $versioningBE, 'FAIL', $uuid,'Version Check Failed !',$validateMessage); + return $this->returnVersioningMessage( + 200, + 'Version Check Failed !', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + $validateMessage + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, $versioningFE, $appVersioningBE, $versioningBE, 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Database connection error !', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, $versioningFE, $appVersioningBE, $versioningBE, 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Eloquent transaction error !', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + $e->getMessage() + ); + } + } + } catch (\Exception $e) { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Unable to parsing JSON versioning !', + 'errStatus' => $e->getMessage() + ]); + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, $versioningFE, $appVersioningBE, $versioningBE, 'FAIL', $uuid,'Unable to parsing JSON versioning !',$e->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Unable to parsing JSON versioning !', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + $e->getMessage() + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, $versioningFE, $appVersioningBE, $versioningBE, 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Database connection error !', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, $versioningFE, $appVersioningBE, $versioningBE, 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Eloquent transaction error !', + $appVersioningBE, + $versioningBE, + $appVersioningFE, + $versioningFE, + $e->getMessage() + ); + } + } + } else { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Version Check Failed !', + 'errStatus' => 'Cannot establish response with the server' + ]); + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, null, $appVersioningBE, null, 'FAIL', $uuid,'Version Check failed !','Cannot establish response with the server'); + return $this->returnVersioningMessage( + 200, + 'Version Check Failed !', + $appVersioningBE, + null, + $appVersioningFE, + null, + 'Cannot establish response with the server' + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, null, $appVersioningBE, null, 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Database connection error !', + $appVersioningBE, + null, + $appVersioningFE, + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, null, $appVersioningBE, null, 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Eloquent transaction error !', + $appVersioningBE, + null, + $appVersioningFE, + null, + $e->getMessage() + ); + } + } + } else { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Version Check Failed !', + 'errStatus' => 'Cannot establish connection with the server' + ]); + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, null, $appVersioningBE, null, 'FAIL', $uuid,'Version Check Failed !','Cannot establish connection with the server'); + return $this->returnVersioningMessage( + 200, + 'Version Check Failed !', + $appVersioningBE, + null, + $appVersioningFE, + null, + 'Cannot establish connection with the server' + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, null, $appVersioningBE, null, 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Database connection error !', + $appVersioningBE, + null, + $appVersioningFE, + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendVersioningErrNotify($appVersioningFE, null, $appVersioningBE, null, 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnVersioningMessage( + 200, + 'Eloquent transaction error !', + $appVersioningBE, + null, + $appVersioningFE, + null, + $e->getMessage() + ); + } + } + } + } + + public function versioningFetch(Request $request) { + $validator = Validator::make($request->all(),[ + 'appServicesReferrer' => ['required', 'in:FE'] + ]); + + $uuid = AppHelper::Instance()->get_guid(); + $endpoint = 'api/v1/version/fetch'; + $versionFetch = 'https://raw.githubusercontent.com/Nicklas373/Hana-PDF/versioning/changelog.json'; + + // Carbon timezone + date_default_timezone_set('Asia/Jakarta'); + $now = Carbon::now('Asia/Jakarta'); + $startProc = $now->format('Y-m-d H:i:s'); + + if ($validator->fails()) { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Validation Failed!', + 'errStatus' => $validator->messages() + ]); + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Version fetch failed !',$validator->messages()); + return $this->returnCoreMessage( + 200, + 'Version fetch failed !', + null, + $validator->errors()->all() + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnMessage( + 200, + 'Database connection error !', + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnMessage( + 200, + 'Eloquent transaction error !', + null, + $e->getMessage() + ); + } + } else { + if (appHelper::instance()->checkWebAvailable($versionFetch)) { + $response = Http::get($versionFetch); + if ($response->successful()) { + $data = $response->json(); + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => null, + 'errStatus' => null + ]); + return $this->returnMessage( + 200, + 'OK', + $data, + null + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnMessage( + 200, + 'Database connection error !', + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnMessage( + 200, + 'Eloquent transaction error !', + null, + $e->getMessage() + ); + } + } else { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Versioning Fetch Failed !', + 'errStatus' => 'Cannot establish response with the server' + ]); + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Version fetch failed !','Cannot establish response with the server'); + return $this->returnMessage( + 200, + 'Version fetch failed !', + null, + 'Cannot establish response with the server' + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnMessage( + 200, + 'Database connection error !', + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnMessage( + 200, + 'Eloquent transaction error !', + null, + $ex->getMessage() + ); + } + } + } else { + try { + DB::table('appLogs')->insert([ + 'processId' => $uuid, + 'errReason' => 'Versioning Fetch Failed !', + 'errStatus' => 'Cannot establish connection with the server' + ]); + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Version fetch failed !','Cannot establish connection with the server'); + return $this->returnMessage( + 200, + 'Version fetch failed !', + null, + 'Cannot establish response with the server' + ); + } catch (QueryException $ex) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Database connection error !',$ex->getMessage()); + return $this->returnMessage( + 200, + 'Database connection error !', + null, + $ex->getMessage() + ); + } catch (\Exception $e) { + NotificationHelper::Instance()->sendErrGlobalNotify($endpoint, 'Version Fetch', 'FAIL', $uuid,'Eloquent transaction error !', $e->getMessage()); + return $this->returnMessage( + 200, + 'Eloquent transaction error !', + null, + $ex->getMessage() + ); + } + } + } + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index b3a45d1c..d7637978 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -81,4 +81,26 @@ protected function returnFileMesage($status, $message, $files, $errors) 'errors' => $errors ], $status); } + + protected function returnMessage($status, $message, $response, $errors) { + return response()->json([ + 'status' => $status, + 'message'=> $message, + 'response' => $response, + 'errors' => $errors + ], $status); + } + + protected function returnVersioningMessage($status, $message, $beVersioning, $beGitVersioning, $feVersioning, $feGitVersioning, $errors) + { + return response()->json([ + 'status' => $status, + 'message'=> $message, + 'beVersioning' => $beVersioning, + 'beGitVersioning' => $beGitVersioning, + 'feVersioning' => $feVersioning, + 'feGitVersioning' => $feGitVersioning, + 'errors' => $errors + ], $status); + } } diff --git a/routes/api.php b/routes/api.php index 6bbc6701..60e79113 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,6 +11,7 @@ use App\Http\Controllers\Api\Core\mergeController; use App\Http\Controllers\Api\Core\splitController; use App\Http\Controllers\Api\Core\watermarkController; +use App\Http\Controllers\Api\versionController; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; @@ -59,6 +60,12 @@ Route::post('proc/all', [notifyLogController::class, 'getAllLogs']); }); +Route::middleware(['auth:api'],['throttle:api'])->prefix('v1/version')->group(function() { + // API v1 Backend PDF Version Validation Route + Route::post('check', [versionController::class, 'versioningCheck']); + Route::post('fetch', [versionController::class, 'versioningFetch']); +}); + Route::fallback(function () { try { return response()->json(['message' => 'Route not found'], 404);