Merge branch 'dev' of bitbucket.org:jubilian/nhance-enrollment into dev
This commit is contained in:
commit
02931bd6d8
@ -183,3 +183,5 @@ CORS_MAX_AGE=7200
|
|||||||
CORS_DEBUG=true
|
CORS_DEBUG=true
|
||||||
|
|
||||||
APP_SIGNATURE =
|
APP_SIGNATURE =
|
||||||
|
TOKENTIMEOUT =
|
||||||
|
JWT_SECRET =
|
||||||
@ -7,7 +7,7 @@ Options -Indexes
|
|||||||
|
|
||||||
|
|
||||||
## ADDED for - block any script execution inside folder of public
|
## ADDED for - block any script execution inside folder of public
|
||||||
<If "%{REQUEST_URI} =~ m#/(logo|add_image_upload|e_card_imgs|assets|claim_sample_forms|sample_import_excel|writable)/#">
|
<If "%{REQUEST_URI} =~ m#/(logo|add_image_upload|e_card_imgs|claim_sample_forms|sample_import_excel|writable)/#">
|
||||||
Deny from all
|
Deny from all
|
||||||
# Disable PHP engine
|
# Disable PHP engine
|
||||||
<IfModule mod_php.c>
|
<IfModule mod_php.c>
|
||||||
|
|||||||
85
app/Config/Acl.php
Normal file
85
app/Config/Acl.php
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Config;
|
||||||
|
|
||||||
|
class Acl
|
||||||
|
{
|
||||||
|
public array $rules = [
|
||||||
|
|
||||||
|
// ===================== PUBLIC / AUTH =====================
|
||||||
|
'#^/login#' => ['public' => true],
|
||||||
|
'#^/logout#' => ['public' => true],
|
||||||
|
'#^/auth#' => ['public' => true],
|
||||||
|
'#^/oauth2callback#' => ['public' => true],
|
||||||
|
'#^/loginPos#' => ['public' => true],
|
||||||
|
'#^/getVerifyPosMobileNo#' => ['public' => true],
|
||||||
|
'#^/getVerifiedPosUserData#' => ['public' => true],
|
||||||
|
'#^/swagger#' => ['roles' => [ADMIN_ROLE_ID]],
|
||||||
|
'#^/fedeploy#' => ['roles' => [ADMIN_ROLE_ID]],
|
||||||
|
|
||||||
|
// ===================== PUBLIC DOWNLOADS / FORMS =====================
|
||||||
|
'#^/download-#' => ['public' => true],
|
||||||
|
'#^/claim-form-download#' => ['public' => true],
|
||||||
|
'#^/claims-feedback-form#' => ['public' => true],
|
||||||
|
'#^/autobookstackLogin#' => ['public' => true],
|
||||||
|
|
||||||
|
// ===================== DASHBOARD =====================
|
||||||
|
'#^/dashboard#' => [
|
||||||
|
'roles' => [ HEAD_ROLE_ID,ADMIN_ROLE_ID, MANAGER_ROLE_ID, STAFF_ROLE_ID, ACCOUNT_MANAGER_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== USER MANAGEMENT =====================
|
||||||
|
'#^/user#' => [
|
||||||
|
'roles' => [ HEAD_ROLE_ID,ADMIN_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== CLIENT =====================
|
||||||
|
'#^/client#' => [
|
||||||
|
'roles' => [ HEAD_ROLE_ID,ADMIN_ROLE_ID, MANAGER_ROLE_ID, ACCOUNT_MANAGER_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== EMPLOYEE / ENROLLMENT =====================
|
||||||
|
'#^/employee#' => [
|
||||||
|
'roles' => [ HEAD_ROLE_ID,ADMIN_ROLE_ID, MANAGER_ROLE_ID, ACCOUNT_MANAGER_ROLE_ID],
|
||||||
|
'teams' => [ENROLLMENT_TEAM_ID]
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== MASTERS =====================
|
||||||
|
'#^/master#' => [
|
||||||
|
'roles' => [ HEAD_ROLE_ID,ADMIN_ROLE_ID, MANAGER_ROLE_ID, ACCOUNT_MANAGER_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
'#^/util#' => [
|
||||||
|
'roles' => [ HEAD_ROLE_ID,ADMIN_ROLE_ID, MANAGER_ROLE_ID, ACCOUNT_MANAGER_ROLE_ID,STAFF_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== LOGS =====================
|
||||||
|
'#^/logs#' => [
|
||||||
|
'roles' => [ADMIN_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== INTERNAL TEST =====================
|
||||||
|
'#^/test#' => [
|
||||||
|
'roles' => [ADMIN_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
|
||||||
|
// ===================== API (JWT / SIGNED) =====================
|
||||||
|
'#^/api#' => ['public' => true],
|
||||||
|
'#^/employeeRest#' => ['public' => true],
|
||||||
|
'#^/clientApi#' => ['public' => true],
|
||||||
|
// ===================== CLI =====================
|
||||||
|
'#^/cli/#' => ['public' => true],
|
||||||
|
|
||||||
|
// ===================== DEFAULT DENY (ZERO TRUST) =====================
|
||||||
|
'#^/#' => [
|
||||||
|
'roles' => [ADMIN_ROLE_ID],
|
||||||
|
'teams' => []
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
@ -17,6 +17,10 @@ use App\Filters\VerifyAppSignature;
|
|||||||
use App\Filters\AuthJWT;
|
use App\Filters\AuthJWT;
|
||||||
use App\Filters\Cors;
|
use App\Filters\Cors;
|
||||||
use App\Filters\GlobalPostFileUploadGuard;
|
use App\Filters\GlobalPostFileUploadGuard;
|
||||||
|
use App\Filters\SecurityInputFilter;
|
||||||
|
use App\Filters\AclFilter;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Filters extends BaseConfig
|
class Filters extends BaseConfig
|
||||||
{
|
{
|
||||||
@ -41,6 +45,8 @@ class Filters extends BaseConfig
|
|||||||
'Cors' => Cors::class,
|
'Cors' => Cors::class,
|
||||||
'appSignature' => VerifyAppSignature::class,
|
'appSignature' => VerifyAppSignature::class,
|
||||||
'GlobalPostFileUploadGuard' => GlobalPostFileUploadGuard::class,
|
'GlobalPostFileUploadGuard' => GlobalPostFileUploadGuard::class,
|
||||||
|
'SecurityInputFilter' => SecurityInputFilter::class,
|
||||||
|
'AclFilter' => AclFilter::class,
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -54,7 +60,9 @@ class Filters extends BaseConfig
|
|||||||
public array $globals = [
|
public array $globals = [
|
||||||
'before' => [
|
'before' => [
|
||||||
'HttpRequestLog' => ['except' => 'cli/*'],
|
'HttpRequestLog' => ['except' => 'cli/*'],
|
||||||
|
'AclFilter' => ['except' => ['login', 'logout', 'auth/*', 'oauth2callback','claim-form-download', 'claims-feedback-form', 'autobookstackLogin','/employeeRest/*','processjob']],
|
||||||
'Cors',
|
'Cors',
|
||||||
|
'SecurityInputFilter' => ['except' => ['notification/create','test_mail'] ],
|
||||||
'GlobalPostFileUploadGuard',
|
'GlobalPostFileUploadGuard',
|
||||||
// 'invalidchars',
|
// 'invalidchars',
|
||||||
],
|
],
|
||||||
|
|||||||
@ -453,9 +453,11 @@ $routes->group("/api", ["filter" => "authJWT"], function ($routes) {
|
|||||||
|
|
||||||
// $routes->post("employeeRest/createOrUpdateEmployeePolicySiAmount", "EmployeeRestController::createOrUpdateEmployeePolicySiAmount");
|
// $routes->post("employeeRest/createOrUpdateEmployeePolicySiAmount", "EmployeeRestController::createOrUpdateEmployeePolicySiAmount");
|
||||||
// $routes->post("employeeRest/calculatePremium", "EmployeeRestController::calculatePremium");
|
// $routes->post("employeeRest/calculatePremium", "EmployeeRestController::calculatePremium");
|
||||||
|
// $routes->post("updateMpin", "RestAuthenticationController::updateMpin");
|
||||||
$routes->group("employeeRest", ['filter' => ['appSignature' , 'authJWT'] ], function ($routes) {
|
$routes->group("employeeRest", ['filter' => ['appSignature' , 'authJWT'] ], function ($routes) {
|
||||||
|
|
||||||
|
$routes->post('logout', 'RestAuthenticationController::logout');
|
||||||
|
|
||||||
// $routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
|
// $routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
|
||||||
|
|
||||||
$routes->post("storeFireBase", "EmployeeRestController::storeFireBase");
|
$routes->post("storeFireBase", "EmployeeRestController::storeFireBase");
|
||||||
|
|||||||
@ -2320,6 +2320,13 @@ class EmployeeRestController extends AdminController
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isset($array['base_policy']) && !empty($array['base_policy']))
|
||||||
|
{
|
||||||
|
$openForEnrollmentValue = (int) $this->findThePolicyIsOpenForEnrollment($array['base_policy'], $emp_code);
|
||||||
|
}else{
|
||||||
|
$openForEnrollmentValue = $array['open_for_enrollment'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$policyTypeData = $this->policyTypeModel->where('id',$array['policy_type_id'])->get()->getRow();
|
$policyTypeData = $this->policyTypeModel->where('id',$array['policy_type_id'])->get()->getRow();
|
||||||
$responce['policy_name'] = $policyTypeData->long_name;
|
$responce['policy_name'] = $policyTypeData->long_name;
|
||||||
@ -2329,7 +2336,7 @@ class EmployeeRestController extends AdminController
|
|||||||
$responce['client_id'] = $array['client_id'];
|
$responce['client_id'] = $array['client_id'];
|
||||||
$responce['client_policy_id'] = $array['id'];
|
$responce['client_policy_id'] = $array['id'];
|
||||||
$responce['is_addon'] = $array['is_addon'];
|
$responce['is_addon'] = $array['is_addon'];
|
||||||
$responce['OpenForEnrollment'] = $array['open_for_enrollment'];
|
$responce['OpenForEnrollment'] = $openForEnrollmentValue;
|
||||||
$responce['policy_terms'] = $decodedArray;
|
$responce['policy_terms'] = $decodedArray;
|
||||||
$responce['policy_type_id'] = $array['policy_type_id'];
|
$responce['policy_type_id'] = $array['policy_type_id'];
|
||||||
//$responce['is_member_modify_allowed'] = $array['is_member_modify_allowed'];
|
//$responce['is_member_modify_allowed'] = $array['is_member_modify_allowed'];
|
||||||
@ -2708,8 +2715,12 @@ class EmployeeRestController extends AdminController
|
|||||||
$array_list = [];
|
$array_list = [];
|
||||||
foreach ($client_policy_id as $key => $value)
|
foreach ($client_policy_id as $key => $value)
|
||||||
{
|
{
|
||||||
// $policy = $this->clientPolicyModel->where('id',$value)->where('open_for_enrollment',1)->find();
|
|
||||||
$policy = $this->findThePolicyIsOpenForEnrollment($client_policy_id, $emp_code);
|
$clientPolicyData = $this->clientPolicyModel->where('client_id',$client_id)
|
||||||
|
->where('id',$value)
|
||||||
|
->where('is_active', 1)
|
||||||
|
->first();
|
||||||
|
$policy = $this->findThePolicyIsOpenForEnrollment($clientPolicyData['base_policy'], $emp_code);
|
||||||
if($policy)
|
if($policy)
|
||||||
{
|
{
|
||||||
$this->myLogger->logme("error", 'client policy id = '.$value.' is open for enrollment');
|
$this->myLogger->logme("error", 'client policy id = '.$value.' is open for enrollment');
|
||||||
|
|||||||
@ -9,6 +9,7 @@ use Psr\Log\LoggerInterface;
|
|||||||
|
|
||||||
use App\Models\UserModel;
|
use App\Models\UserModel;
|
||||||
use App\Models\AuthHistoryModel;
|
use App\Models\AuthHistoryModel;
|
||||||
|
use App\Libraries\AuthLogout;
|
||||||
|
|
||||||
class LoginController extends BaseController
|
class LoginController extends BaseController
|
||||||
{
|
{
|
||||||
@ -30,20 +31,22 @@ class LoginController extends BaseController
|
|||||||
public function receiveGoogleOAuthResponse()
|
public function receiveGoogleOAuthResponse()
|
||||||
{
|
{
|
||||||
$UserModel = new UserModel();
|
$UserModel = new UserModel();
|
||||||
//echo 'DONE';die();
|
// echo 'DONE';die();
|
||||||
if ($this->request->getGet('code')) {
|
if ($this->request->getGet('code')) {
|
||||||
$code = (string) $this->request->getGet('code');
|
$code = (string) $this->request->getGet('code');
|
||||||
log_message('error', 'Get OAuth Responce Code Sucessfully');
|
log_message('error', 'Get OAuth Responce Code Sucessfully');
|
||||||
log_message('error', 'OAuthResponceCode : `'.$code.'`');
|
log_message('error', 'OAuthResponceCode : `'.$code.'`');
|
||||||
$value = googleOAuthLogin($this->request->getGet('code'));
|
$value = googleOAuthLogin($this->request->getGet('code'));
|
||||||
|
// log_message('error', "OAuthResponceCode :" . json_encode($value));
|
||||||
if($value){
|
if($value){
|
||||||
|
// print_r($value);//die;
|
||||||
$user = $UserModel->getUserByEmail($value->email);
|
$user = $UserModel->getUserByEmail($value->email);
|
||||||
if($user){
|
if($user){
|
||||||
if($user->is_active !== '0'){
|
if($user->is_active !== '0'){
|
||||||
|
|
||||||
$user_team = $UserModel->getUserTeamsByUserID($user->id);
|
$user_team = $UserModel->getUserTeamsByUserID($user->id);
|
||||||
// dd($user_team);
|
// dd($user_team);
|
||||||
|
session()->regenerate(true);
|
||||||
$session_data = [
|
$session_data = [
|
||||||
'isLoggedIn' => True ,
|
'isLoggedIn' => True ,
|
||||||
'userid' => $user->id,
|
'userid' => $user->id,
|
||||||
@ -54,9 +57,13 @@ class LoginController extends BaseController
|
|||||||
$path = getenv('cookie.Path');
|
$path = getenv('cookie.Path');
|
||||||
$domain = getenv('cookie.Domain');
|
$domain = getenv('cookie.Domain');
|
||||||
$https = getenv('ccokie.secure');
|
$https = getenv('ccokie.secure');
|
||||||
setcookie('session_data', json_encode($session_data), time() + 12 * 60 * 60, $path, $domain, $https, true);
|
// setcookie('session_data', json_encode($session_data), time() + 12 * 60 * 60, $path, $domain, $https, true);
|
||||||
set_session_data($session_data);
|
set_session_data($session_data);
|
||||||
|
|
||||||
|
// Bind session to device
|
||||||
|
set_session_data(['fingerprint' => hash('sha256',
|
||||||
|
($this->request->getUserAgent()->getAgentString() . '|' . ($this->request->getIPAddress()
|
||||||
|
)))]);
|
||||||
log_message('error', 'Set The UserId : `'. $user->id .'` in Session');
|
log_message('error', 'Set The UserId : `'. $user->id .'` in Session');
|
||||||
log_message('error', 'User Login Sucessfully');
|
log_message('error', 'User Login Sucessfully');
|
||||||
|
|
||||||
@ -66,13 +73,13 @@ class LoginController extends BaseController
|
|||||||
}else{
|
}else{
|
||||||
log_message('error', 'User Not Active');
|
log_message('error', 'User Not Active');
|
||||||
session()->setFlashdata('error', 'User Not Active');
|
session()->setFlashdata('error', 'User Not Active');
|
||||||
return redirect()->to(base_url('login'));
|
return AuthLogout::logout();
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
log_message('error', 'User Not Registered');
|
log_message('error', 'User Not Registered');
|
||||||
session()->setFlashdata('error', 'User Not Registered');
|
session()->setFlashdata('error', 'User Not Registered');
|
||||||
return redirect()->to(base_url('login'));
|
return AuthLogout::logout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,14 +101,16 @@ class LoginController extends BaseController
|
|||||||
// setcookie('session_data', '', time() - 3600, $path);
|
// setcookie('session_data', '', time() - 3600, $path);
|
||||||
// return redirect()->to(base_url('login'));
|
// return redirect()->to(base_url('login'));
|
||||||
|
|
||||||
$path = getenv('cookie.Path');
|
// $path = getenv('cookie.Path');
|
||||||
session()->destroy();
|
// session()->destroy();
|
||||||
// setcookie('session_data', '', time() - 3600, $path);
|
// // setcookie('session_data', '', time() - 3600, $path);
|
||||||
$path = getenv('cookie.Path');
|
// $path = getenv('cookie.Path');
|
||||||
$domain = getenv('cookie.Domain');
|
// $domain = getenv('cookie.Domain');
|
||||||
$https = getenv('cookie.secure');
|
// $https = getenv('cookie.secure');
|
||||||
setcookie('session_data',null, time() -3600, $path, $domain, $https, true);
|
// setcookie('session_data',null, time() -3600, $path, $domain, $https, true);
|
||||||
return redirect()->to(base_url('login'));
|
// return redirect()->to(base_url('login'));
|
||||||
|
|
||||||
|
return AuthLogout::logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -167,6 +167,13 @@ class RestAuthenticationController extends AdminController
|
|||||||
|
|
||||||
if (isset($employeeData['employee_id']))
|
if (isset($employeeData['employee_id']))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||||
|
$check = canSendOtp($employeeData);
|
||||||
|
if (!$check['allowed']) {
|
||||||
|
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||||
|
}
|
||||||
|
|
||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithMobileNumber: Employee verified with ID = " . $employeeData['employee_id']);
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithMobileNumber: Employee verified with ID = " . $employeeData['employee_id']);
|
||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
log_message('error', '************************ PRE END ********************************');
|
log_message('error', '************************ PRE END ********************************');
|
||||||
@ -264,10 +271,11 @@ class RestAuthenticationController extends AdminController
|
|||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Received Email ID = " . $email);
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Received Email ID = " . $email);
|
||||||
|
|
||||||
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
|
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
|
||||||
// print_r($empdata); die;
|
|
||||||
|
|
||||||
$otp = random_int(100000, 999999);
|
$otp = random_int(100000, 999999);
|
||||||
|
|
||||||
|
//only retail policy
|
||||||
if(empty($empdata)){
|
if(empty($empdata)){
|
||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: No employee data found both PRE & POST");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: No employee data found both PRE & POST");
|
||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
@ -323,8 +331,15 @@ class RestAuthenticationController extends AdminController
|
|||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Using PRE data");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Using PRE data");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (isset($employeeData['employee_id']))
|
if (isset($employeeData['employee_id']))
|
||||||
{
|
{
|
||||||
|
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||||
|
$check = canSendOtp($employeeData);
|
||||||
|
if (!$check['allowed']) {
|
||||||
|
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||||
|
}
|
||||||
|
|
||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Valid employee found, generating OTP");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Valid employee found, generating OTP");
|
||||||
|
|
||||||
@ -579,6 +594,12 @@ class RestAuthenticationController extends AdminController
|
|||||||
if ($HrData)
|
if ($HrData)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||||
|
$check = canSendOtp($HrData);
|
||||||
|
if (!$check['allowed']) {
|
||||||
|
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||||
|
}
|
||||||
|
|
||||||
$sql = "UPDATE level_contacts SET otp = ? WHERE mobile = ? AND contact_type = 'client' AND is_active = 1";
|
$sql = "UPDATE level_contacts SET otp = ? WHERE mobile = ? AND contact_type = 'client' AND is_active = 1";
|
||||||
|
|
||||||
$db = db_connect();
|
$db = db_connect();
|
||||||
@ -638,6 +659,12 @@ class RestAuthenticationController extends AdminController
|
|||||||
|
|
||||||
if ($HrData) {
|
if ($HrData) {
|
||||||
|
|
||||||
|
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||||
|
$check = canSendOtp($HrData);
|
||||||
|
if (!$check['allowed']) {
|
||||||
|
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$sql = "
|
$sql = "
|
||||||
@ -951,6 +978,12 @@ class RestAuthenticationController extends AdminController
|
|||||||
$old_mpin = $this->request->getJSON()->old_mpin;
|
$old_mpin = $this->request->getJSON()->old_mpin;
|
||||||
$mpin = $this->request->getJSON()->new_mpin;
|
$mpin = $this->request->getJSON()->new_mpin;
|
||||||
|
|
||||||
|
if($old_mpin == $mpin)
|
||||||
|
{
|
||||||
|
$result = ['mpin_verification' => false , 'message' => "New MPIN must be different from the old MPIN"];
|
||||||
|
return $this->respond(['status' => 'failed','code' => 404,'data' => $result],200);
|
||||||
|
}
|
||||||
|
|
||||||
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email_id, 'mobile_number' => $mobile_number, 'old_mpin' => $old_mpin ]);
|
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email_id, 'mobile_number' => $mobile_number, 'old_mpin' => $old_mpin ]);
|
||||||
// print_r($empdata); die;
|
// print_r($empdata); die;
|
||||||
|
|
||||||
@ -959,7 +992,7 @@ class RestAuthenticationController extends AdminController
|
|||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
log_message('error', '************************ PRE END ********************************');
|
log_message('error', '************************ PRE END ********************************');
|
||||||
|
|
||||||
$result = ['user_verification' => false , 'message' => "User not found"];
|
$result = ['mpin_verification' => false , 'message' => "Old MPIN is incorrect"];
|
||||||
return $this->respond(['status' => 'failed','code' => 404,'data' => $result],200);
|
return $this->respond(['status' => 'failed','code' => 404,'data' => $result],200);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1238,7 +1271,7 @@ class RestAuthenticationController extends AdminController
|
|||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - checkMpin: Mpin - Exist");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - checkMpin: Mpin - Exist");
|
||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
log_message('error', '************************ PRE END ********************************');
|
log_message('error', '************************ PRE END ********************************');
|
||||||
return $this->respond(['status' => 'success','code' => 200,'data' => "", 'message' => "Mpin - exist" , 'Mpin' =>$employeeData["mpin"], 'is_mpin_skipped' => $employeeData['is_mpin_skipped'], 'is_biometric_enabled' => $employeeData['is_biometric_enabled']],200);
|
return $this->respond(['status' => 'success','code' => 200,'data' => "", 'message' => "Mpin - exist" , 'Mpin' =>$employeeData["mpin"], 'is_mpin_skipped' => $employeeData['is_mpin_skipped'] ?? 0, 'is_biometric_enabled' => $employeeData['is_biometric_enabled'] ?? 0 ],200);
|
||||||
} else {
|
} else {
|
||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - checkMpin: Mpin - not found in PRE so call the thirdpartapi to the POST to check the MPIN");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - checkMpin: Mpin - not found in PRE so call the thirdpartapi to the POST to check the MPIN");
|
||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
@ -1868,5 +1901,55 @@ class RestAuthenticationController extends AdminController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function logout()
|
||||||
|
{
|
||||||
|
$authHeader = $this->request->getHeaderLine('Authorization');
|
||||||
|
|
||||||
|
if (!$authHeader) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Authorization token missing'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate JWT (your hardened function)
|
||||||
|
$result = JWTToken::validateJWT($authHeader);
|
||||||
|
|
||||||
|
if ($result['status'] !== true) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Invalid or expired token'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = $result['decoded'];
|
||||||
|
$userId = $decoded['id'] ?? null;
|
||||||
|
|
||||||
|
if (!$userId) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => false,
|
||||||
|
'message' => 'Invalid token payload'
|
||||||
|
], 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify user type
|
||||||
|
if (isset($decoded['emp_code'])) {
|
||||||
|
$model = new EmployeeModel();
|
||||||
|
} else {
|
||||||
|
$model = new LevelContactModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalidate token server-side
|
||||||
|
$model->update($userId, [
|
||||||
|
'token_time_out' => null
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->respond([
|
||||||
|
'status' => true,
|
||||||
|
'message' => 'Logged out successfully'
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
156
app/Filters/AclFilter.php
Normal file
156
app/Filters/AclFilter.php
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use CodeIgniter\HTTP\RequestInterface;
|
||||||
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
|
use CodeIgniter\Filters\FilterInterface;
|
||||||
|
use Config\Acl;
|
||||||
|
|
||||||
|
use App\Libraries\AuthLogout;
|
||||||
|
|
||||||
|
class AclFilter implements FilterInterface
|
||||||
|
{
|
||||||
|
public function before(RequestInterface $request, $arguments = null)
|
||||||
|
{
|
||||||
|
// ===================== CLI BYPASS =====================
|
||||||
|
if (is_cli()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================== PATH NORMALIZATION =====================
|
||||||
|
$uri = service('uri');
|
||||||
|
|
||||||
|
// Raw path: /PHP828APPS/ruc/nhance/index.php/dashboard/view
|
||||||
|
$fullPath = '/' . ltrim($uri->getPath(), '/');
|
||||||
|
|
||||||
|
// Base path: /PHP828APPS/ruc/nhance
|
||||||
|
$basePath = rtrim(parse_url(base_url(), PHP_URL_PATH), '/');
|
||||||
|
|
||||||
|
// Remove base path
|
||||||
|
if ($basePath && str_starts_with($fullPath, $basePath)) {
|
||||||
|
$path = substr($fullPath, strlen($basePath));
|
||||||
|
} else {
|
||||||
|
$path = $fullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove index.php if present
|
||||||
|
if (str_starts_with($path, '/index.php')) {
|
||||||
|
$path = substr($path, strlen('/index.php'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalize
|
||||||
|
$path = '/' . ltrim($path, '/');
|
||||||
|
|
||||||
|
// Fallback
|
||||||
|
if ($path === '') {
|
||||||
|
$path = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// echo'<br>BASH PATH: ' . base_url();
|
||||||
|
// echo'<br>ACL RAW PATH: ' . $fullPath;
|
||||||
|
// echo'<br>ACL BASE PATH: ' . $basePath;
|
||||||
|
// echo'<br>ACL FINAL PATH: ' . $path;
|
||||||
|
// ===================== LOAD ACL =====================
|
||||||
|
$acl = new Acl();
|
||||||
|
$rules = $acl->rules;
|
||||||
|
// print_rr($rules);die;
|
||||||
|
// ===================== MATCH RULE =====================
|
||||||
|
$matchedRule = null;
|
||||||
|
|
||||||
|
foreach ($rules as $pattern => $rule) {
|
||||||
|
// echo "$pattern".'---------<br>';
|
||||||
|
if (preg_match($pattern, $path)) {
|
||||||
|
// echo "matched - $pattern";
|
||||||
|
$matchedRule = $rule;
|
||||||
|
break; // FIRST MATCH WINS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print_r($matchedRule);//die;
|
||||||
|
// ===================== NO RULE = DENY =====================
|
||||||
|
if ($matchedRule === null) {
|
||||||
|
return $this->deny($path, 'No ACL rule matched');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== PUBLIC ROUTE =====================
|
||||||
|
if (!empty($matchedRule['public'])) {
|
||||||
|
return; // ALLOW
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== AUTH CHECK =====================
|
||||||
|
if (!check_session()) {
|
||||||
|
// For API requests return 401 JSON
|
||||||
|
if ($request->isAJAX() || str_starts_with($path, '/api') || str_starts_with($path, '/employeeRest')) {
|
||||||
|
return service('response')
|
||||||
|
->setStatusCode(401)
|
||||||
|
->setJSON(['error' => 'Unauthorized']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For web redirect to login
|
||||||
|
return AuthLogout::logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== GET USER CONTEXT =====================
|
||||||
|
|
||||||
|
$userRole = check_role(); //
|
||||||
|
$userTeams = user_team(); // must return array of TEAM IDs
|
||||||
|
|
||||||
|
$allowedRoles = $matchedRule['roles'] ?? [];
|
||||||
|
$allowedTeams = $matchedRule['teams'] ?? [];
|
||||||
|
// ===================== ROLE FIRST =====================
|
||||||
|
if (!empty($allowedRoles) && in_array((int)$userRole, $allowedRoles, true)) {
|
||||||
|
return; // ALLOW
|
||||||
|
}
|
||||||
|
// ===================== TEAM FALLBACK =====================
|
||||||
|
if (!empty($allowedTeams) && is_array($userTeams)) {
|
||||||
|
foreach ($userTeams as $teamId) {
|
||||||
|
if (in_array($teamId, $allowedTeams, true)) {
|
||||||
|
return; // ALLOW
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ===================== DENY =====================
|
||||||
|
return $this->deny($path, 'Role/Team not permitted');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||||
|
{
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== DENY HANDLER =====================
|
||||||
|
protected function deny(string $path, string $reason)
|
||||||
|
{
|
||||||
|
log_message('error', 'ACL BLOCKED: {user} {path} - {reason}', [
|
||||||
|
'user' => session()->get('userid') ?? 'guest',
|
||||||
|
'path' => $path,
|
||||||
|
'reason' => $reason,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// API / AJAX → JSON
|
||||||
|
$request = service('request');
|
||||||
|
if ($request->isAJAX() || str_starts_with($path, '/api') || str_starts_with($path, '/employeeRest')) {
|
||||||
|
return service('response')
|
||||||
|
->setStatusCode(403)
|
||||||
|
->setJSON([
|
||||||
|
'error' => 'Forbidden',
|
||||||
|
'message' => 'You do not have permission to access this resource'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = service('response');
|
||||||
|
$response->setStatusCode(403);
|
||||||
|
$response->setBody(view('errors/404', [
|
||||||
|
'message' => '403 Access denied - You do not have permission to access this resource'
|
||||||
|
]));
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
// Web → nice 403 page or simple text
|
||||||
|
return service('response')
|
||||||
|
->setStatusCode(403)
|
||||||
|
->setBody('403 Forbidden - Access denied - You do not have permission to access this resource');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -18,65 +18,116 @@ use App\Models\LevelContactModel;
|
|||||||
|
|
||||||
class AuthJWT implements FilterInterface
|
class AuthJWT implements FilterInterface
|
||||||
{
|
{
|
||||||
|
// public function before(RequestInterface $request, $arguments = null)
|
||||||
|
// {
|
||||||
|
// $jwt = $request->getHeaderLine('Authorization');
|
||||||
|
|
||||||
|
// if ($jwt) {
|
||||||
|
// if (JWTToken::validateJWT($jwt)) {
|
||||||
|
// $data = JWTToken::validateJWT($jwt);
|
||||||
|
// $data = json_decode($data);
|
||||||
|
|
||||||
|
// $id = $data->decoded->id;
|
||||||
|
// if(isset($data->decoded->emp_code)){
|
||||||
|
// $model = new EmployeeModel();
|
||||||
|
// $user_data = $model->where('id', $id)->first();
|
||||||
|
|
||||||
|
// if($user_data['token_time_out'] > time()){
|
||||||
|
// $data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
||||||
|
// $model->update($id, $data);
|
||||||
|
// return true;
|
||||||
|
// }else{
|
||||||
|
|
||||||
|
// // if($user_data['token_time_out'] != "" && $user_data['token_time_out'] != NULL)
|
||||||
|
|
||||||
|
// $data =["token_time_out" => ''];
|
||||||
|
// $model->update($id, $data);
|
||||||
|
// header('Content-Type: application/json');
|
||||||
|
// http_response_code(401);
|
||||||
|
// // $error = json_encode(["status" => 401, "message" => $data->message]);
|
||||||
|
// $error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
||||||
|
// echo $error;
|
||||||
|
// exit;
|
||||||
|
// }
|
||||||
|
// }else{
|
||||||
|
// $model = new LevelContactModel();
|
||||||
|
// $hr_data = $model->where('id', $id)->first();
|
||||||
|
|
||||||
|
// if($hr_data['token_time_out'] > time()){
|
||||||
|
// $data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
||||||
|
// $model->update($id, $data);
|
||||||
|
// return true;
|
||||||
|
// }else{
|
||||||
|
// $data =["token_time_out" => ''];
|
||||||
|
// $model->update($id, $data);
|
||||||
|
// header('Content-Type: application/json');
|
||||||
|
// http_response_code(401);
|
||||||
|
// // $error = json_encode(["status" => 401, "message" => $data->message]);
|
||||||
|
// $error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
||||||
|
// echo $error;
|
||||||
|
// exit;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// header('Content-Type: application/json');
|
||||||
|
// http_response_code(403);
|
||||||
|
// $error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
|
||||||
|
// echo $error;
|
||||||
|
// exit();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
public function before(RequestInterface $request, $arguments = null)
|
public function before(RequestInterface $request, $arguments = null)
|
||||||
{
|
{
|
||||||
$jwt = $request->getHeaderLine('Authorization');
|
$authHeader = $request->getHeaderLine('Authorization');
|
||||||
|
|
||||||
if ($jwt) {
|
if (!$authHeader) {
|
||||||
if (JWTToken::validateJWT($jwt)) {
|
return $this->reject(403, 'Access Forbidden');
|
||||||
$data = JWTToken::validateJWT($jwt);
|
}
|
||||||
$data = json_decode($data);
|
|
||||||
|
|
||||||
$id = $data->decoded->id;
|
$result = JWTToken::validateJWT($authHeader);
|
||||||
if(isset($data->decoded->emp_code)){
|
|
||||||
|
if ($result['status'] !== true) {
|
||||||
|
return $this->reject(401, $result['message']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$decoded = $result['decoded'];
|
||||||
|
$id = $decoded['id'] ?? null;
|
||||||
|
|
||||||
|
if (!$id) {
|
||||||
|
return $this->reject(401, 'Invalid token payload');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($decoded['emp_code'])) {
|
||||||
$model = new EmployeeModel();
|
$model = new EmployeeModel();
|
||||||
$user_data = $model->where('id', $id)->first();
|
|
||||||
|
|
||||||
if($user_data['token_time_out'] > time()){
|
|
||||||
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
|
||||||
$model->update($id, $data);
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
|
|
||||||
// if($user_data['token_time_out'] != "" && $user_data['token_time_out'] != NULL)
|
|
||||||
|
|
||||||
$data =["token_time_out" => ''];
|
|
||||||
$model->update($id, $data);
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
http_response_code(401);
|
|
||||||
// $error = json_encode(["status" => 401, "message" => $data->message]);
|
|
||||||
$error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
|
||||||
echo $error;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
$model = new LevelContactModel();
|
|
||||||
$hr_data = $model->where('id', $id)->first();
|
|
||||||
|
|
||||||
if($hr_data['token_time_out'] > time()){
|
|
||||||
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
|
||||||
$model->update($id, $data);
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
$data =["token_time_out" => ''];
|
|
||||||
$model->update($id, $data);
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
http_response_code(401);
|
|
||||||
// $error = json_encode(["status" => 401, "message" => $data->message]);
|
|
||||||
$error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
|
||||||
echo $error;
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
header('Content-Type: application/json');
|
$model = new LevelContactModel();
|
||||||
http_response_code(403);
|
$id = $decoded['pre_hr_id'] ?? null;
|
||||||
$error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
|
|
||||||
echo $error;
|
|
||||||
exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$user = $model->find($id);
|
||||||
|
|
||||||
|
if (!$user || $user['token_time_out'] <= time()) {
|
||||||
|
$model->update($id, ['token_time_out' => null]);
|
||||||
|
return $this->reject(401, 'Token expired');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh sliding expiration
|
||||||
|
$model->update($id, [
|
||||||
|
'token_time_out' => time() + getenv('TOKENTIMEOUT')
|
||||||
|
]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function reject(int $code, string $message)
|
||||||
|
{
|
||||||
|
return service('response')
|
||||||
|
->setStatusCode($code)
|
||||||
|
->setJSON(['status' => $code, 'message' => $message])
|
||||||
|
->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||||
|
|||||||
@ -5,12 +5,29 @@ use CodeIgniter\Filters\FilterInterface;
|
|||||||
use CodeIgniter\HTTP\RequestInterface;
|
use CodeIgniter\HTTP\RequestInterface;
|
||||||
use CodeIgniter\HTTP\ResponseInterface;
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
|
|
||||||
|
use App\Libraries\AuthLogout;
|
||||||
|
|
||||||
class AuthMVC implements FilterInterface
|
class AuthMVC implements FilterInterface
|
||||||
{
|
{
|
||||||
public function before(RequestInterface $request, $arguments = null)
|
public function before(RequestInterface $request, $arguments = null)
|
||||||
{
|
{
|
||||||
if (!check_session() && !check_cookie()) {
|
if (!check_session())
|
||||||
return redirect()->to(base_url('/login'));
|
{
|
||||||
|
return AuthLogout::logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (!check_cookie())
|
||||||
|
// {
|
||||||
|
// return AuthLogout::logout();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Fingerprint validation
|
||||||
|
$fp = hash('sha256',
|
||||||
|
$request->getUserAgent()->getAgentString() . '|' . $request->getIPAddress()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (session()->get('fingerprint') !== $fp) {
|
||||||
|
return AuthLogout::logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,11 +107,11 @@ class Cors implements FilterInterface
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->log('CORS filter initialized', [
|
// $this->log('CORS filter initialized', [
|
||||||
'allowed_origins' => $this->allowedOrigins,
|
// 'allowed_origins' => $this->allowedOrigins,
|
||||||
'allow_credentials' => $this->allowCredentials,
|
// 'allow_credentials' => $this->allowCredentials,
|
||||||
'allowed_methods' => $this->allowedMethods,
|
// 'allowed_methods' => $this->allowedMethods,
|
||||||
]);
|
// ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,7 +143,7 @@ class Cors implements FilterInterface
|
|||||||
|
|
||||||
// If wildcard present in configuration, allow any origin
|
// If wildcard present in configuration, allow any origin
|
||||||
if (in_array('*', $this->allowedOrigins, true)) {
|
if (in_array('*', $this->allowedOrigins, true)) {
|
||||||
$this->log('Origin allowed: wildcard match', ['origin' => $origin]);
|
// $this->log('Origin allowed: wildcard match', ['origin' => $origin]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,10 +159,10 @@ class Cors implements FilterInterface
|
|||||||
// 1. Exact match (including scheme and port)
|
// 1. Exact match (including scheme and port)
|
||||||
// Example: https://example.com matches https://example.com
|
// Example: https://example.com matches https://example.com
|
||||||
if (strcasecmp($allowed, $origin) === 0) {
|
if (strcasecmp($allowed, $origin) === 0) {
|
||||||
$this->log('Origin allowed: exact match', [
|
// $this->log('Origin allowed: exact match', [
|
||||||
'origin' => $origin,
|
// 'origin' => $origin,
|
||||||
'matched_rule' => $allowed
|
// 'matched_rule' => $allowed
|
||||||
]);
|
// ]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,11 +178,11 @@ class Cors implements FilterInterface
|
|||||||
|
|
||||||
// Check if origin host ends with the allowed root domain
|
// Check if origin host ends with the allowed root domain
|
||||||
if ($originHost === $allowedRoot || str_ends_with($originHost, '.' . $allowedRoot)) {
|
if ($originHost === $allowedRoot || str_ends_with($originHost, '.' . $allowedRoot)) {
|
||||||
$this->log('Origin allowed: wildcard subdomain match', [
|
// $this->log('Origin allowed: wildcard subdomain match', [
|
||||||
'origin' => $origin,
|
// 'origin' => $origin,
|
||||||
'matched_rule' => $allowed,
|
// 'matched_rule' => $allowed,
|
||||||
'origin_host' => $originHost
|
// 'origin_host' => $originHost
|
||||||
]);
|
// ]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,11 +191,11 @@ class Cors implements FilterInterface
|
|||||||
// Example: example.com matches both http://example.com and https://example.com
|
// Example: example.com matches both http://example.com and https://example.com
|
||||||
else {
|
else {
|
||||||
if (strcasecmp($allowed, $originHost) === 0) {
|
if (strcasecmp($allowed, $originHost) === 0) {
|
||||||
$this->log('Origin allowed: host match (scheme-less)', [
|
// $this->log('Origin allowed: host match (scheme-less)', [
|
||||||
'origin' => $origin,
|
// 'origin' => $origin,
|
||||||
'matched_rule' => $allowed,
|
// 'matched_rule' => $allowed,
|
||||||
'origin_host' => $originHost
|
// 'origin_host' => $originHost
|
||||||
]);
|
// ]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,11 +320,11 @@ class Cors implements FilterInterface
|
|||||||
// Preflight is sent by browsers before actual cross-origin requests
|
// Preflight is sent by browsers before actual cross-origin requests
|
||||||
// to check if the actual request is safe to send
|
// to check if the actual request is safe to send
|
||||||
if ($method === 'OPTIONS') {
|
if ($method === 'OPTIONS') {
|
||||||
$this->log('Preflight request received', [
|
// $this->log('Preflight request received', [
|
||||||
'origin' => $origin,
|
// 'origin' => $origin,
|
||||||
'method' => $method,
|
// 'method' => $method,
|
||||||
'uri' => (string) $request->getUri()
|
// 'uri' => (string) $request->getUri()
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
// Validate origin - reject if not allowed
|
// Validate origin - reject if not allowed
|
||||||
if (empty($origin) || !$this->isOriginAllowed($origin)) {
|
if (empty($origin) || !$this->isOriginAllowed($origin)) {
|
||||||
@ -346,10 +346,10 @@ class Cors implements FilterInterface
|
|||||||
$response->setStatusCode(204);
|
$response->setStatusCode(204);
|
||||||
$response->setBody('');
|
$response->setBody('');
|
||||||
|
|
||||||
$this->log('Preflight approved', [
|
// $this->log('Preflight approved', [
|
||||||
'origin' => $origin,
|
// 'origin' => $origin,
|
||||||
'allowed_methods' => $this->allowedMethods
|
// 'allowed_methods' => $this->allowedMethods
|
||||||
]);
|
// ]);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
@ -392,10 +392,10 @@ class Cors implements FilterInterface
|
|||||||
// Add CORS headers to the response
|
// Add CORS headers to the response
|
||||||
$this->addCorsHeaders($response, $request, $origin, false);
|
$this->addCorsHeaders($response, $request, $origin, false);
|
||||||
|
|
||||||
$this->log('CORS headers added to response', [
|
// $this->log('CORS headers added to response', [
|
||||||
'origin' => $origin,
|
// 'origin' => $origin,
|
||||||
'status' => $response->getStatusCode()
|
// 'status' => $response->getStatusCode()
|
||||||
]);
|
// ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
130
app/Filters/SecurityInputFilter.php
Normal file
130
app/Filters/SecurityInputFilter.php
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filters;
|
||||||
|
|
||||||
|
use CodeIgniter\Filters\FilterInterface;
|
||||||
|
use CodeIgniter\HTTP\RequestInterface;
|
||||||
|
use CodeIgniter\HTTP\ResponseInterface;
|
||||||
|
use Config\Services;
|
||||||
|
|
||||||
|
class SecurityInputFilter implements FilterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* High-confidence XSS patterns only
|
||||||
|
* (low false-positive set)
|
||||||
|
**/
|
||||||
|
|
||||||
|
protected array $xssPatterns = [
|
||||||
|
// Script execution
|
||||||
|
'/<\s*script\b/i',
|
||||||
|
'/<\/\s*script\s*>/i',
|
||||||
|
|
||||||
|
// JavaScript execution vectors
|
||||||
|
'/javascript\s*:/i',
|
||||||
|
'/vbscript\s*:/i',
|
||||||
|
'/data\s*:\s*text\/html/i',
|
||||||
|
|
||||||
|
// Inline event handlers (strong signal)
|
||||||
|
'/on\w+\s*=\s*["\']?/i',
|
||||||
|
|
||||||
|
// Dangerous HTML tags
|
||||||
|
'/<\s*iframe\b/i',
|
||||||
|
'/<\s*object\b/i',
|
||||||
|
'/<\s*embed\b/i',
|
||||||
|
'/<\s*applet\b/i',
|
||||||
|
'/<\s*img\b/i',
|
||||||
|
|
||||||
|
// Image-based execution
|
||||||
|
'/<\s*img\b[^>]*on\w+/i',
|
||||||
|
|
||||||
|
// SVG-based execution (modern bypass)
|
||||||
|
'/<\s*svg\b/i',
|
||||||
|
'/<\s*math\b/i',
|
||||||
|
|
||||||
|
// Meta refresh redirect
|
||||||
|
'/<\s*meta\b[^>]*http-equiv\s*=\s*["\']?refresh/i',
|
||||||
|
|
||||||
|
// HTML injection via src/href
|
||||||
|
'/<\s*\w+\b[^>]*(src|href)\s*=\s*["\']?\s*(javascript|data)\s*:/i'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
public function before(RequestInterface $request, $arguments = null)
|
||||||
|
{
|
||||||
|
$logger = Services::mylogger();
|
||||||
|
$response = Services::response();
|
||||||
|
|
||||||
|
// Collect all user-controlled input
|
||||||
|
$inputs = array_merge(
|
||||||
|
$request->getGet(),
|
||||||
|
$request->getPost()
|
||||||
|
);
|
||||||
|
|
||||||
|
if (empty($inputs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($inputs as $field => $value) {
|
||||||
|
if (is_array($value)) {
|
||||||
|
$value = json_encode($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 1: Canonicalization (VERY IMPORTANT)
|
||||||
|
$canonical = $this->canonicalize($value);
|
||||||
|
|
||||||
|
// Step 2: Trim (hygiene)
|
||||||
|
$canonical = trim($canonical);
|
||||||
|
|
||||||
|
// Step 3: Detection (signal-only)
|
||||||
|
if ($this->detectXss($canonical)) {
|
||||||
|
|
||||||
|
// 🔐 Log intent, not data
|
||||||
|
$logger->logme('critical','SECURITY_BLOCKED_REQUEST - '. json_encode([
|
||||||
|
'ip' => $request->getIPAddress(),
|
||||||
|
'method' => $request->getMethod(),
|
||||||
|
'uri' => current_url(),
|
||||||
|
'field' => $field,
|
||||||
|
'attack' => 'XSS_PATTERN',
|
||||||
|
'length' => strlen($canonical),
|
||||||
|
'hash' => hash('sha256', $canonical),
|
||||||
|
]));
|
||||||
|
|
||||||
|
// ⛔ Block request
|
||||||
|
return $response
|
||||||
|
->setStatusCode(403)
|
||||||
|
->setJSON([
|
||||||
|
'status' => 403,
|
||||||
|
'error' => 'Forbidden',
|
||||||
|
'message' => 'Malicious input detected'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Canonicalization prevents encoded bypass
|
||||||
|
*/
|
||||||
|
private function canonicalize(string $value): string
|
||||||
|
{
|
||||||
|
$value = urldecode($value);
|
||||||
|
$value = html_entity_decode($value, ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
||||||
|
|
||||||
|
// Remove invisible control characters
|
||||||
|
return preg_replace('/[\x00-\x1F\x7F]/u', '', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function detectXss(string $value): bool
|
||||||
|
{
|
||||||
|
foreach ($this->xssPatterns as $pattern) {
|
||||||
|
if (preg_match($pattern, $value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,24 +4,175 @@ namespace App\Helpers;
|
|||||||
|
|
||||||
class HttpRequestHelper
|
class HttpRequestHelper
|
||||||
{
|
{
|
||||||
public static function getRequestInfo()
|
public static function getRequestInfo(): array
|
||||||
{
|
{
|
||||||
$request = service('request');
|
$request = service('request');
|
||||||
|
|
||||||
|
$uaString = $request->getHeaderLine('User-Agent');
|
||||||
|
|
||||||
|
// Detect platform & browser using robust fallback logic
|
||||||
|
[$platform, $browser] = self::detectFromUserAgent($uaString);
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'ip' => $request->getIPAddress(),
|
'ip' => $request->getIPAddress(),
|
||||||
'platform' => $request->getUserAgent()->getPlatform(),
|
'platform' => $platform,
|
||||||
'browser' => ($request->getUserAgent()->getBrowser().' '.$request->getUserAgent()->getVersion()),
|
'browser' => $browser,
|
||||||
'method' => $request->getMethod(),
|
'method' => strtoupper($request->getMethod()),
|
||||||
'endpoint' => $request->uri->getPath(),
|
'endpoint' => $request->uri->getPath(),
|
||||||
'getparams' => $request->uri->getSegments(),
|
'getparams' => json_encode($request->uri->getSegments(), JSON_UNESCAPED_UNICODE),
|
||||||
'postparams' => $request->getPost()
|
'postparams' => self::sanitizePostForLog($request->getPost()),
|
||||||
];
|
];
|
||||||
|
|
||||||
$data['method'] = (isset($data['method']) ? strtoupper($data['method']) : $data['method']);
|
|
||||||
$data['getparams'] = is_array($data['getparams']) ? json_encode($data['getparams']) : $data['getparams'];
|
|
||||||
$data['postparams'] = is_array($data['postparams']) ? json_encode($data['postparams']) : $data['postparams'];
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect platform & browser from UA string (reliable fallback)
|
||||||
|
*/
|
||||||
|
private static function detectFromUserAgent(string $ua): array
|
||||||
|
{
|
||||||
|
$uaLower = strtolower($ua);
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// PLATFORM DETECTION
|
||||||
|
// =========================
|
||||||
|
$platform = 'Unknown';
|
||||||
|
|
||||||
|
if (str_contains($uaLower, 'windows nt 11') || str_contains($uaLower, 'windows 11')) {
|
||||||
|
$platform = 'Windows 11';
|
||||||
|
} elseif (str_contains($uaLower, 'windows nt 10')) {
|
||||||
|
$platform = 'Windows 10';
|
||||||
|
} elseif (str_contains($uaLower, 'windows nt 6.3')) {
|
||||||
|
$platform = 'Windows 8.1';
|
||||||
|
} elseif (str_contains($uaLower, 'windows nt 6.2')) {
|
||||||
|
$platform = 'Windows 8';
|
||||||
|
} elseif (str_contains($uaLower, 'windows nt 6.1')) {
|
||||||
|
$platform = 'Windows 7';
|
||||||
|
} elseif (str_contains($uaLower, 'windows nt 6.0')) {
|
||||||
|
$platform = 'Windows Vista';
|
||||||
|
} elseif (str_contains($uaLower, 'windows nt 5.1') || str_contains($uaLower, 'windows xp')) {
|
||||||
|
$platform = 'Windows XP';
|
||||||
|
} elseif (str_contains($uaLower, 'android')) {
|
||||||
|
$platform = 'Android';
|
||||||
|
} elseif (str_contains($uaLower, 'iphone')) {
|
||||||
|
$platform = 'iOS (iPhone)';
|
||||||
|
} elseif (str_contains($uaLower, 'ipad')) {
|
||||||
|
$platform = 'iOS (iPad)';
|
||||||
|
} elseif (str_contains($uaLower, 'ipod')) {
|
||||||
|
$platform = 'iOS (iPod)';
|
||||||
|
} elseif (str_contains($uaLower, 'mac os') || str_contains($uaLower, 'macintosh')) {
|
||||||
|
$platform = 'Mac OS';
|
||||||
|
} elseif (str_contains($uaLower, 'cros')) {
|
||||||
|
$platform = 'Chrome OS';
|
||||||
|
} elseif (str_contains($uaLower, 'linux')) {
|
||||||
|
$platform = 'Linux';
|
||||||
|
} elseif (str_contains($uaLower, 'freebsd')) {
|
||||||
|
$platform = 'FreeBSD';
|
||||||
|
} elseif (str_contains($uaLower, 'openbsd')) {
|
||||||
|
$platform = 'OpenBSD';
|
||||||
|
} elseif (str_contains($uaLower, 'netbsd')) {
|
||||||
|
$platform = 'NetBSD';
|
||||||
|
} elseif (str_contains($uaLower, 'unix')) {
|
||||||
|
$platform = 'Unix';
|
||||||
|
} elseif (str_contains($uaLower, 'symbian')) {
|
||||||
|
$platform = 'Symbian';
|
||||||
|
} elseif (str_contains($uaLower, 'blackberry')) {
|
||||||
|
$platform = 'BlackBerry';
|
||||||
|
} elseif (str_contains($uaLower, 'tizen')) {
|
||||||
|
$platform = 'Tizen';
|
||||||
|
} elseif (str_contains($uaLower, 'webos')) {
|
||||||
|
$platform = 'WebOS';
|
||||||
|
} elseif (str_contains($uaLower, 'kaios')) {
|
||||||
|
$platform = 'KaiOS';
|
||||||
|
} elseif (str_contains($uaLower, 'harmonyos')) {
|
||||||
|
$platform = 'HarmonyOS';
|
||||||
|
} elseif (str_contains($uaLower, 'watchos')) {
|
||||||
|
$platform = 'watchOS';
|
||||||
|
} elseif (str_contains($uaLower, 'tv os') || str_contains($uaLower, 'tvos')) {
|
||||||
|
$platform = 'tvOS';
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// BROWSER / CLIENT DETECTION
|
||||||
|
// =========================
|
||||||
|
$browser = 'Unknown';
|
||||||
|
|
||||||
|
// Bots & tools first
|
||||||
|
if (preg_match('/googlebot|bingbot|slurp|duckduckbot|baiduspider|yandexbot|sogou|exabot|facebot|ia_archiver/i', $ua)) {
|
||||||
|
$browser = 'Search Bot';
|
||||||
|
} elseif (preg_match('/postman/i', $ua)) {
|
||||||
|
$browser = 'Postman';
|
||||||
|
} elseif (preg_match('/insomnia/i', $ua)) {
|
||||||
|
$browser = 'Insomnia';
|
||||||
|
} elseif (preg_match('/curl/i', $ua)) {
|
||||||
|
$browser = 'curl';
|
||||||
|
} elseif (preg_match('/wget/i', $ua)) {
|
||||||
|
$browser = 'wget';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Real browsers
|
||||||
|
elseif (preg_match('/edg\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Edge ' . $m[1];
|
||||||
|
} elseif (preg_match('/opr\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Opera ' . $m[1];
|
||||||
|
} elseif (preg_match('/vivaldi\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Vivaldi ' . $m[1];
|
||||||
|
} elseif (preg_match('/brave\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Brave ' . $m[1];
|
||||||
|
} elseif (preg_match('/chrome\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Chrome ' . $m[1];
|
||||||
|
} elseif (preg_match('/firefox\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Firefox ' . $m[1];
|
||||||
|
} elseif (preg_match('/safari\/([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Safari ' . $m[1];
|
||||||
|
} elseif (preg_match('/msie\s([\d\.]+)/i', $ua, $m) || preg_match('/trident\/.*rv:([\d\.]+)/i', $ua, $m)) {
|
||||||
|
$browser = 'Internet Explorer ' . $m[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// In-app browsers
|
||||||
|
elseif (preg_match('/fbav|fban/i', $ua)) {
|
||||||
|
$browser = 'Facebook In-App Browser';
|
||||||
|
} elseif (preg_match('/instagram/i', $ua)) {
|
||||||
|
$browser = 'Instagram In-App Browser';
|
||||||
|
} elseif (preg_match('/linkedinapp/i', $ua)) {
|
||||||
|
$browser = 'LinkedIn In-App Browser';
|
||||||
|
} elseif (preg_match('/twitter/i', $ua)) {
|
||||||
|
$browser = 'Twitter/X In-App Browser';
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$platform, $browser];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove sensitive fields before logging POST
|
||||||
|
*/
|
||||||
|
private static function sanitizePostForLog(array $post): string
|
||||||
|
{
|
||||||
|
if (empty($post)) {
|
||||||
|
return json_encode([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sensitiveKeys = [
|
||||||
|
'password', 'pass', 'pwd',
|
||||||
|
'token', 'access_token', 'refresh_token',
|
||||||
|
'secret', 'api_key', 'authorization',
|
||||||
|
'otp', 'pin'
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($post as $k => $v) {
|
||||||
|
foreach ($sensitiveKeys as $sk) {
|
||||||
|
if (stripos($k, $sk) !== false) {
|
||||||
|
$post[$k] = '***MASKED***';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_encode($post, JSON_UNESCAPED_UNICODE);
|
||||||
|
}
|
||||||
|
|
||||||
public static function add($payload)
|
public static function add($payload)
|
||||||
{return $payload['a'] + $payload['b'];}
|
{
|
||||||
|
return $payload['a'] + $payload['b'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,13 @@ use App\Models\LevelContactModel;
|
|||||||
|
|
||||||
class JWTToken
|
class JWTToken
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private const ALLOWED_ALG = 'HS512';
|
||||||
|
|
||||||
|
|
||||||
public static function encode($data =null)
|
public static function encode($data =null)
|
||||||
{
|
{
|
||||||
$secret_Key ="secret";
|
$secret_Key = env('JWT_SECRET');
|
||||||
|
|
||||||
$request_data = (array)$data;
|
$request_data = (array)$data;
|
||||||
|
|
||||||
@ -47,30 +51,79 @@ class JWTToken
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function validateJWT($jwt)
|
// public static function validateJWT($jwt)
|
||||||
|
// {
|
||||||
|
// $jwtParts = explode(' ', $jwt);
|
||||||
|
|
||||||
|
// // print_r($jwtParts);
|
||||||
|
// if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// $token = $jwtParts[1];
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512'));
|
||||||
|
// return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
|
||||||
|
// } catch (ExpiredException $e) {
|
||||||
|
// return json_encode(['status' => false, 'message' => 'Token has expired']);
|
||||||
|
// } catch (BeforeValidException $e) {
|
||||||
|
// return json_encode(['status' => false, 'message' => 'Token is not yet valid']);
|
||||||
|
// } catch (SignatureInvalidException $e) {
|
||||||
|
// return json_encode(['status' => false, 'message' => 'Token signature is invalid']);
|
||||||
|
// } catch (\Exception $e) {
|
||||||
|
// return json_encode(['status' => false, 'message' => 'An error occurred while decoding the token']);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static function validateJWT(string $authHeader)
|
||||||
{
|
{
|
||||||
$jwtParts = explode(' ', $jwt);
|
// 1️⃣ Validate Authorization header
|
||||||
|
if (!preg_match('/^Bearer\s(\S+)$/', $authHeader, $matches)) {
|
||||||
// print_r($jwtParts);
|
return ['status' => false, 'message' => 'Invalid Authorization header'];
|
||||||
if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = $jwtParts[1];
|
$token = $matches[1];
|
||||||
|
|
||||||
|
// 2️⃣ Decode JWT header manually
|
||||||
|
$jwtParts = explode('.', $token);
|
||||||
|
if (count($jwtParts) !== 3) {
|
||||||
|
return ['status' => false, 'message' => 'Malformed JWT'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = json_decode(base64_decode(strtr($jwtParts[0], '-_', '+/')), true);
|
||||||
|
|
||||||
|
// 3️⃣ Reject missing or NONE algorithm
|
||||||
|
if (
|
||||||
|
empty($header['alg']) ||
|
||||||
|
$header['alg'] === 'none' ||
|
||||||
|
$header['alg'] !== self::ALLOWED_ALG
|
||||||
|
) {
|
||||||
|
return ['status' => false, 'message' => 'Invalid or unsupported JWT algorithm'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4️⃣ Enforce signature validation
|
||||||
try {
|
try {
|
||||||
$decoded = JWT::decode($token, new Key("secret", 'HS512'));
|
$decoded = JWT::decode(
|
||||||
return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
|
$token,
|
||||||
} catch (ExpiredException $e) {
|
new Key(env('JWT_SECRET'), self::ALLOWED_ALG)
|
||||||
return json_encode(['status' => false, 'message' => 'Token has expired']);
|
);
|
||||||
} catch (BeforeValidException $e) {
|
|
||||||
return json_encode(['status' => false, 'message' => 'Token is not yet valid']);
|
|
||||||
} catch (SignatureInvalidException $e) {
|
|
||||||
return json_encode(['status' => false, 'message' => 'Token signature is invalid']);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return json_encode(['status' => false, 'message' => 'An error occurred while decoding the token']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return [
|
||||||
|
'status' => true,
|
||||||
|
'decoded' => (array) $decoded
|
||||||
|
];
|
||||||
|
|
||||||
|
} catch (ExpiredException $e) {
|
||||||
|
return ['status' => false, 'message' => 'Token expired'];
|
||||||
|
} catch (BeforeValidException $e) {
|
||||||
|
return ['status' => false, 'message' => 'Token not yet valid'];
|
||||||
|
} catch (SignatureInvalidException $e) {
|
||||||
|
return ['status' => false, 'message' => 'Invalid token signature'];
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return ['status' => false, 'message' => 'Token validation failed'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ if(!function_exists('check_cookie')){
|
|||||||
'userProfile' => $value['userProfile'],
|
'userProfile' => $value['userProfile'],
|
||||||
'user_team' => $user_team,
|
'user_team' => $user_team,
|
||||||
];
|
];
|
||||||
set_session_data($session_data);
|
// set_session_data($session_data);
|
||||||
// $this->getUserDeviceInfo($user->id, 'NhanceUser');
|
// $this->getUserDeviceInfo($user->id, 'NhanceUser');
|
||||||
// return redirect()->to(base_url('/dashboard/view'));
|
// return redirect()->to(base_url('/dashboard/view'));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -677,6 +677,32 @@ if (!function_exists('check_pay_by_employee_or_company')) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!function_exists('canSendOtp')) {
|
||||||
|
function canSendOtp(array $row, int $limitSeconds = 60): array
|
||||||
|
{
|
||||||
|
// If OTP does not exist → allow
|
||||||
|
if (empty($row['otp']) || empty($row['updated_at'])) {
|
||||||
|
return ['allowed' => true];
|
||||||
|
}
|
||||||
|
|
||||||
|
$lastUpdated = strtotime($row['updated_at']);
|
||||||
|
$currentTime = time();
|
||||||
|
|
||||||
|
// Calculate expiry time
|
||||||
|
$allowedAfter = $lastUpdated + $limitSeconds;
|
||||||
|
|
||||||
|
// If still within limit → block
|
||||||
|
if ($currentTime < $allowedAfter) {
|
||||||
|
return [
|
||||||
|
'allowed' => false,
|
||||||
|
'retry_after' => $allowedAfter - $currentTime
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['allowed' => true];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!function_exists('getLatestGMCPolicy')) {
|
if (!function_exists('getLatestGMCPolicy')) {
|
||||||
|
|
||||||
function getLatestGMCPolicy(array $empPolicy)
|
function getLatestGMCPolicy(array $empPolicy)
|
||||||
|
|||||||
42
app/Libraries/AuthLogout.php
Normal file
42
app/Libraries/AuthLogout.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Libraries;
|
||||||
|
|
||||||
|
use CodeIgniter\HTTP\RedirectResponse;
|
||||||
|
|
||||||
|
class AuthLogout
|
||||||
|
{
|
||||||
|
public static function logout(): RedirectResponse
|
||||||
|
{
|
||||||
|
$session = session();
|
||||||
|
|
||||||
|
// Regenerate session ID (kills fixation)
|
||||||
|
$session->regenerate(true);
|
||||||
|
|
||||||
|
// Destroy CI session
|
||||||
|
$session->destroy();
|
||||||
|
|
||||||
|
// Kill PHP session cookie safely
|
||||||
|
if (ini_get('session.use_cookies')) {
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
|
||||||
|
setcookie(
|
||||||
|
session_name(), // DO NOT hardcode cookie name
|
||||||
|
null,
|
||||||
|
time() - 42000,
|
||||||
|
$params['path'],
|
||||||
|
$params['domain'],
|
||||||
|
$params['secure'],
|
||||||
|
$params['httponly']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
session_write_close();
|
||||||
|
|
||||||
|
// Redirect with anti-cache headers
|
||||||
|
return redirect()->to(base_url('login'))
|
||||||
|
->setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
||||||
|
->setHeader('Pragma', 'no-cache')
|
||||||
|
->setHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user