MERGE_TEST_LOGIN_API&MINOR

This commit is contained in:
Ubuntu 2025-12-12 17:34:27 +05:30
commit dfa0df5388
14 changed files with 1539 additions and 239 deletions

View File

@ -20,6 +20,7 @@ class Database extends Config
* use if no other is specified.
*/
public string $defaultGroup = 'default';
public string $enableSSL;
/**
* The default database connection.
@ -38,6 +39,7 @@ class Database extends Config
'DBCollat' => 'utf8_general_ci',
'swapPre' => '',
'encrypt' => false,
// 'encrypt' => ['ssl_verify' => true,'ssl_ca' => ROOTPATH .'ca.pem'],
'compress' => false,
'strictOn' => false,
'failover' => [],
@ -95,5 +97,17 @@ class Database extends Config
if (ENVIRONMENT === 'testing') {
$this->defaultGroup = 'tests';
}
$this->enableSSL = env('DB_SSL_ENABLE') ?? false;
if ($this->enableSSL === true || $this->enableSSL === 'true' || $this->enableSSL === 1 || $this->enableSSL === '1') {
// Enable SSL authentication
$this->default['encrypt'] = [
'ssl_ca' => ROOTPATH . 'ca.pem',
'ssl_verify' => true,
];
}
}
}

View File

@ -21,7 +21,7 @@ class Feature extends BaseConfig
* - property $filtersInfo, instead of $filterInfo
* - CodeIgniter\Router\RouteCollection::getFiltersForRoute(), instead of getFilterForRoute()
*/
public bool $multipleFilters = false;
public bool $multipleFilters = true;
/**
* Use improved new auto routing instead of the default legacy version.

View File

@ -12,8 +12,10 @@ use CodeIgniter\Filters\SecureHeaders;
use App\Filters\AuthMVC;
use App\Filters\HttpRequestLog;
use App\Filters\CloseDbConnection;
use App\Filters\VerifyAppSignature;
use App\Filters\AuthJWT;
use App\Filters\Cors;
class Filters extends BaseConfig
{
@ -34,7 +36,10 @@ class Filters extends BaseConfig
'authMVC' => AuthMVC::class,
'HttpRequestLog' => HttpRequestLog::class,
'authJWT' => AuthJWT::class,
'CloseDbConnection' => CloseDbConnection::class
'CloseDbConnection' => CloseDbConnection::class,
'Cors' => Cors::class,
'appSignature' => VerifyAppSignature::class,
];
/**
@ -47,11 +52,13 @@ class Filters extends BaseConfig
public array $globals = [
'before' => [
'HttpRequestLog' => ['except' => 'cli/*'],
'Cors',
// 'csrf',
// 'invalidchars',
],
'after' => [
'CloseDbConnection'
'CloseDbConnection',
'Cors',
// 'secureheaders',
],
];

View File

@ -3,6 +3,14 @@
use CodeIgniter\Router\RouteCollection;
// Allow OPTIONS for all routes
$routes->options('(:any)', function() {
// This will never be called because the CORS filter returns early
// But having this route ensures OPTIONS isn't rejected as 404
});
/**
* @var RouteCollection $routes
*/
@ -431,45 +439,21 @@ $routes->cli('cli/check_bounce_mail_cli', 'MasterController::testCheckBounceMail
$routes->cli('cli/app_check_list', 'MasterController::appCheckList');
$routes->cli('cli/new_gdrive_token', 'GoogleDriveController::generateNewGoogleDriveAccessToken');
//Employee login api's
$routes->post("/employeeRest/verifyEmployeeNumber", "RestAuthenticationController::verifyEmployeeWithMobileNumber");
$routes->post("/employeeRest/getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
$routes->post("/employeeRest/verifyEmployeeEmailId", "RestAuthenticationController::verifyEmployeeWithEmailId");
// $routes->post("/employeeRest/saveMpin", "RestAuthenticationController::saveMpin");
//HR login api's
$routes->post("/employeeRest/verifyHrWithMobileNumber", "RestAuthenticationController::verifyHrWithMobileNumber");
$routes->post("/employeeRest/verifyHrWithEmail", "RestAuthenticationController::verifyHrWithEmail");
$routes->post("/employeeRest/getVerifiedHrData", "RestAuthenticationController::getVerifiedHrData");
$routes->group("/api", ["filter" => "authJWT"], function ($routes) {
$routes->post("logined", "RestAuthenticationController::logined");
$routes->post("getId", "RestAuthenticationController::getUserIdFromToken");
});
// MPIN api's
$routes->post("employeeRest/saveMpin", "RestAuthenticationController::saveMpin");
$routes->post("employeeRest/updateMpin", "RestAuthenticationController::updateMpin");
$routes->post("/employeeRest/verifyMpin", "RestAuthenticationController::verifyMpin");
$routes->post("/employeeRest/checkMpin", "RestAuthenticationController::checkMpin");
$routes->post("employeeRest/forgotMPIN", "RestAuthenticationController::forgotMPIN");
$routes->post("employeeRest/updateMobileNumber", "RestAuthenticationController::updateMobileNumber");
// PASSWORD api's
$routes->post("employeeRest/savePassword", "RestAuthenticationController::savePassword");
$routes->post("employeeRest/changePassword", "RestAuthenticationController::changePassword");
$routes->post("employeeRest/verifyPassword", "RestAuthenticationController::verifyPassword");
$routes->post("employeeRest/verifyOtp", "RestAuthenticationController::verifyOtp");
$routes->post("employeeRest/checkPassword", "RestAuthenticationController::checkPassword");
$routes->get("employeeRest/downloadSampleExcel", "EmployeeRestController::downloadSampleExcel");
// $routes->post("employeeRest/createOrUpdateEmployeePolicySiAmount", "EmployeeRestController::createOrUpdateEmployeePolicySiAmount");
// $routes->post("employeeRest/calculatePremium", "EmployeeRestController::calculatePremium");
$routes->group("employeeRest", ["filter" => "authJWT"], function ($routes) {
$routes->group("employeeRest", ['filter' => ['appSignature' , 'authJWT'] ], function ($routes) {
// $routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
@ -515,6 +499,41 @@ $routes->group("employeeRest", ["filter" => "authJWT"], function ($routes) {
$routes->get("hrFileDownload", "EmployeeRestController::hrFileDownload");
$routes->post("hrFileUpload", "EmployeeRestController::hrFileUpload");
$routes->get("copyActiveEmployeeAndDependentDetails", "EmployeeRestController::copyActiveEmployeeAndDependentDetails");
});
$routes->group("employeeRest", ['filter' => ['appSignature'] ], function ($routes) {
//Employee login api's
$routes->post("verifyEmployeeNumber", "RestAuthenticationController::verifyEmployeeWithMobileNumber");
$routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
$routes->post("verifyEmployeeEmailId", "RestAuthenticationController::verifyEmployeeWithEmailId");
// $routes->post("saveMpin", "RestAuthenticationController::saveMpin");
//HR login api's
$routes->post("verifyHrWithMobileNumber", "RestAuthenticationController::verifyHrWithMobileNumber");
$routes->post("verifyHrWithEmail", "RestAuthenticationController::verifyHrWithEmail");
$routes->post("getVerifiedHrData", "RestAuthenticationController::getVerifiedHrData");
// MPIN api's
$routes->post("saveMpin", "RestAuthenticationController::saveMpin");
$routes->post("updateMpin", "RestAuthenticationController::updateMpin");
$routes->post("verifyMpin", "RestAuthenticationController::verifyMpin");
$routes->post("checkMpin", "RestAuthenticationController::checkMpin");
$routes->post("forgotMPIN", "RestAuthenticationController::forgotMPIN");
$routes->post("updateMobileNumber", "RestAuthenticationController::updateMobileNumber");
// PASSWORD api's
$routes->post("savePassword", "RestAuthenticationController::savePassword");
$routes->post("changePassword", "RestAuthenticationController::changePassword");
$routes->post("verifyPassword", "RestAuthenticationController::verifyPassword");
$routes->post("verifyOtp", "RestAuthenticationController::verifyOtp");
$routes->post("checkPassword", "RestAuthenticationController::checkPassword");
$routes->get("downloadSampleExcel", "EmployeeRestController::downloadSampleExcel");
});
$routes->get("getEmployeeActiveOrInactivePolicy", "EmployeeRestController::getEmployeeActiveOrInactivePolicy");
@ -530,7 +549,7 @@ $routes->cli("cli/sendCroneRemainderMail", "DashboardController::sendCroneRemain
$routes->get('enrollOpendAndClose', 'DashboardController::updatePolicyEnrollmentStatus');
$routes->get("sendCroneRemainderMail", "DashboardController::sendCroneRemainderMail");
$routes->get("getEmployeePolicy", "EmployeeRestController::getEmployeePolicy");
// $routes->get("getEmployeePolicy", "EmployeeRestController::getEmployeePolicy");
$routes->get("getAddOnPolicy", "EmployeeRestController::getAddOnPolicy");
$routes->post("addEmployeeAndDependence", "EmployeeRestController::addEmployeeAndDependence");
$routes->post("getPreEmployeePolicyCount", "EmployeeRestController::getPreEmployeePolicyCount");

View File

@ -369,7 +369,7 @@ class EmployeeRestController extends AdminController
$basic_cover_si = $policy_terms->sum_insured;
}
$checkDataExist = $this->employeePolicyModel->where('employee_id',$employee_id)->where('client_policy_id',$client_policy_id)->first();
$checkDataExist = $this->employeePolicyModel->where('employee_id',$employee_id)->where('client_policy_id',$client_policy_id)->where('is_active', 1)->first();
if($checkDataExist){
@ -527,15 +527,29 @@ class EmployeeRestController extends AdminController
if($this->request->getGet('id'))
{
$is_from_copy = $this->request->getGet('is_from_copy') ?? null;
if($is_from_copy == 'false' || $is_from_copy == false || $is_from_copy == 'null' || $is_from_copy == null){
$this->employeeModel->where('id', $this->request->getGet('id') )
->where('is_active', 1 )
->set(array('is_active'=> 0 ))
->update();
}
$query = $this->employeePolicyModel
->where('employee_id', $this->request->getGet('id'))
->where('is_active', 1);
// 👉 Add condition only if client_policy_id exists
$clientPolicyId = $this->request->getGet('client_policy_id') ?? null;
if (!empty($clientPolicyId)) {
$query->where('client_policy_id', $clientPolicyId);
}
$query->set(['is_active' => 0])->update();
$this->employeePolicyModel->where('employee_id',$this->request->getGet('id') )
->where('is_active', 1 )
->set(array('is_active'=> 0 ))
->update();
return $this->respond(['status' => 'success','code' => 200,'data' =>[] ], 200);
}else{
@ -803,12 +817,9 @@ class EmployeeRestController extends AdminController
{
if(isset($result['error_type'])){
$result = $empServiceController->getExcelErrorData($file_id);
return $this->respond(['status' => 'failed', 'code' => 404, 'message' => "file upload failed with errors",'data' => $result], 200);
return $this->respond(['status' => 'failed', 'code' => 404, 'message' => 'The data format is invalid. Click "Next" to view details.','data' => $result], 200);
}else {
$message = "file upload failed with errors";
if(isset($result['error_data'])){
$message = $result['error_data'];
}
$message = "The import file is in an incorrect format. Please compare it with our template file to correct it.";
return $this->respond(['status' => 'failed', 'code' => 404, 'message' => $message,'data' => $result], 200);
}
}
@ -1164,11 +1175,23 @@ class EmployeeRestController extends AdminController
if ($empPolicy) {
$latest_gmc_policy_id = getLatestGMCPolicy((array)$empPolicy);
$result = [];
foreach ($empPolicy as $array) {
// Reset employee array
$empData = $employeeData;
// Reset employee array
// $empData = $employeeData;
$empData = $this->employeeModel
->select('employees.*')
->join('employee_polices', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employees.client_id',$client_id)
->where('employees.client_branch_id',$client_branch_id)
->where('employee_polices.client_policy_id',$array->ClientPolicyId)
->where('employees.is_active', 1 )
->where('employee_polices.is_active', 1 )
->where('employees.is_addon_value',0)
->findAll();
// Removes specific keys from the decoded array and assigns the result to $refusingData
$decodedArray = json_decode($array->Policy_Terms);
@ -1248,7 +1271,14 @@ class EmployeeRestController extends AdminController
}else if($array->policy_type_id == 2 && $this->request->getGet('policy') == 'GMC' )
{
$array->to_be_added_relationship = [];
$array->existing_relationship = [];
if(!empty($latest_gmc_policy_id) && $latest_gmc_policy_id == $array->ClientPolicyId){
$array->copy_dependence_data_enable = true;
}else{
$array->copy_dependence_data_enable = false;
}
// Map family floaters that already exist in the employee table
$familyFloates = $array->Policy_Terms->family_floaters;
@ -1259,7 +1289,7 @@ class EmployeeRestController extends AdminController
if($getSlabAndGridData['slab_rates'][0]['premium_type'] == 1 || $getSlabAndGridData['slab_rates'][0]['premium_type'] == 3)
{
$array->floter_text_heading = 'Floater Sum Insured';
$array->floter_text_description = 'This is a floater sum insured. A floater is a type of sum insured that provides coverage to more than one member ot a family at the same time. Simply put, its a single insurance cover for the entire family.';
$array->floter_text_description = 'This is a floater sum insured. A floater is a type of sum insured that provides coverage to more than one member of a family at the same time. Simply put, its a single insurance cover for the entire family.';
}else{
$array->floter_text_heading = 'Sum Insured';
$array->floter_text_description = '';
@ -1303,6 +1333,8 @@ class EmployeeRestController extends AdminController
$temp['data']['age_validation'] = $this->getAgeRange($decodedArray,$familyFloatesValue);
array_push($array->existing_relationship,$temp['data']['relationship']);
array_push($data,$temp);
unset($empData[$key]);
$floters = array_diff($floters, [$familyFloatesValue]);
@ -1350,6 +1382,7 @@ class EmployeeRestController extends AdminController
$temp2['is_value_exist'] = false;
$temp2['data']['family_floater_key'] = $familyFloatesValue;
$temp2['data']['relationship'] = ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['client_policy_id'] = $array->ClientPolicyId;
$temp2['data']['button_name'] = 'Add '.ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['form_type'] = preg_replace('/\d/', '', $familyFloatesValue);
@ -1359,9 +1392,58 @@ class EmployeeRestController extends AdminController
array_push($data,$temp2);
array_push($array->to_be_added_relationship,['relationship'=>$temp2['data']['relationship'],'age_validation'=>$temp2['data']['age_validation']]);
$array->to_be_added_relationship = array_values(
array_map('unserialize',
array_unique(
array_map('serialize', $array->to_be_added_relationship)
)
)
);
}
}
$array->relationship = [];
foreach ($array->to_be_added_relationship as $key => $value) {
if($value['relationship'] == 'Spouse'){
array_push($array->relationship,['relationship'=>'Spouse','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if($value['relationship'] == 'Child'){
array_push($array->relationship, ['relationship'=>'Son','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
array_push($array->relationship, ['relationship'=>'Daughter','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if($value['relationship'] == 'Parent'){
$Father = array_search('Father',$array->existing_relationship);
$Mother = array_search('Mother',$array->existing_relationship);
if ($Father === false && $Mother === false) {
array_push($array->relationship, ['relationship'=>'Father','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
array_push($array->relationship, ['relationship'=>'Mother','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if ($Father !== false && $Mother === false) {
array_push($array->relationship, ['relationship'=>'Mother','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
} else if ($Mother !== false && $Father === false) {
array_push($array->relationship, ['relationship'=>'Father','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}
}else if($value['relationship'] == 'Parent in law'){
$FatherinLaw = array_search('Father in Law',$array->existing_relationship);
$MotherinLaw = array_search('Mother in Law',$array->existing_relationship);
if ($FatherinLaw === false && $MotherinLaw === false) {
array_push($array->relationship, ['relationship'=>'Father in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
array_push($array->relationship, ['relationship'=>'Mother in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if ($FatherinLaw !== false && $MotherinLaw === false) {
array_push($array->relationship, ['relationship'=>'Mother in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
} else if ($MotherinLaw !== false && $FatherinLaw === false) {
array_push($array->relationship, ['relationship'=>'Father in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}
}
}
// echo '<pre>';
// print_r($array->existing_relationship);
// print_r($array->to_be_added_relationship);
// print_r($array->relationship);
// die;
$array->mapped_family_floaters = $data;
$array->type = "GMC";
$array->family_floaters_of_dependent_and_si_value = $dependent_and_si_value > 0 ? $dependent_and_si_value : 0;
@ -1386,12 +1468,14 @@ class EmployeeRestController extends AdminController
if($checkGmcParentsPolicyExist)
{
$GmcParrentsData = $this->getGmcParrentsPolicy($checkGmcParentsPolicyExist,$emp_code,$client_id,$client_branch_id);
return $this->respond(['status' => 'success','code' => 200,'data' => [$array,$GmcParrentsData]], 200);
// return $this->respond(['status' => 'success','code' => 200,'data' => [$array,$GmcParrentsData]], 200);
$result[] = $array;
$result[] = $GmcParrentsData;
}
if($this->request->getGet('policy') == 'GMC'){
return $this->respond(['status' => 'success','code' => 200,'data' => [$array]], 200);
if($this->request->getGet('policy') == 'GMC' && !$checkGmcParentsPolicyExist){
// return $this->respond(['status' => 'success','code' => 200,'data' => [$array]], 200);
$result[] = $array;
}
}
@ -1399,14 +1483,31 @@ class EmployeeRestController extends AdminController
// $result[] = $array;
}
if(!empty($result) && $this->request->getGet('policy') == 'GMC'){
return $this->respond(['status' => 'success','code' => 200,'data' => $result], 200);
}else{
return $this->respond(['status' => 'success','code' => 200,'data' => []], 200);
}
}else{
return $this->respond(['status' => 'failed','code' => 404,'data' => []], 200);
}
} catch (\Exception $e) {
return $this->respond(['status' => 'failed','code' => 500,'data' => $e->getLine()], 500);
$errorData = [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'code' => $e->getCode(),
'trace' => $e->getTraceAsString(),
'trace_array' => $e->getTrace(), // full array version (optional)
'function' => $e->getTrace()[0]['function'] ?? null,
'class' => $e->getTrace()[0]['class'] ?? null,
];
return $this->respond(['status' => 'failed','code' => 500,'data' => $e->getLine(), 'error_data' => $errorData], 500);
}
}
@ -1414,19 +1515,31 @@ class EmployeeRestController extends AdminController
public function getGmcParrentsPolicy($GmcParrentsPolicy,$emp_code,$client_id,$client_branch_id)
{
$employeeData = $this->employeeModel->where('emp_code',$emp_code)
->where('client_id',$client_id)
->where('client_branch_id',$client_branch_id)
->where('is_active', 1 )
->where('is_addon_value',0)->findAll();
// $employeeData = $this->employeeModel->where('emp_code',$emp_code)
// ->where('client_id',$client_id)
// ->where('client_branch_id',$client_branch_id)
// ->where('is_active', 1 )
// ->where('is_addon_value',0)->findAll();
// return $employeeData;
foreach ($GmcParrentsPolicy as $key => $array) {
$array->to_be_added_relationship = [];
$array->existing_relationship = [];
// Reset employee array
$empData = $employeeData;
// $empData = $employeeData;
$empData = $this->employeeModel
->select('employees.*')
->join('employee_polices', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employees.client_id',$client_id)
->where('employees.client_branch_id',$client_branch_id)
->where('employee_polices.client_policy_id',$array->ClientPolicyId)
->where('employees.is_active', 1 )
->where('employee_polices.is_active', 1 )
->where('employees.is_addon_value',0)
->findAll();
$array->Policy_Terms = json_decode($array->Policy_Terms);
@ -1440,6 +1553,7 @@ class EmployeeRestController extends AdminController
->join('employee_polices', 'employee_polices.employee_id = employees.id')
->where('employees.emp_code',$emp_code)
->where('employees.is_active',1)
->where('employee_polices.is_active',1)
->where('employee_polices.client_policy_id',$array->ClientPolicyId)
->get()
->getResult();
@ -1513,6 +1627,7 @@ class EmployeeRestController extends AdminController
$temp['data']['basic_cover_si'] = isset($employee_policy->basic_cover_si) ? $employee_policy->basic_cover_si : 0;
$temp['data']['age_validation'] = $this->getAgeRange($array->Policy_Terms,$familyFloatesValue);
array_push($array->existing_relationship,$temp['data']['relationship']);
array_push($data,$temp);
unset($empData[$key]);
@ -1559,12 +1674,55 @@ class EmployeeRestController extends AdminController
$temp2['is_value_exist'] = false;
$temp2['data']['family_floater_key'] = $familyFloatesValue;
$temp2['data']['relationship'] = ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['client_policy_id'] = $array->ClientPolicyId;
$temp2['data']['button_name'] = 'Add '.ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['form_type'] = preg_replace('/\d/', '', $familyFloatesValue);
$temp2['data']['age_validation'] = $this->getAgeRange($array->Policy_Terms,$familyFloatesValue);
array_push($data,$temp2);
array_push($array->to_be_added_relationship,['relationship'=>$temp2['data']['relationship'],'age_validation'=>$temp2['data']['age_validation']]);
$array->to_be_added_relationship = array_values(
array_map('unserialize',
array_unique(
array_map('serialize', $array->to_be_added_relationship)
)
)
);
}
}
$array->relationship = [];
foreach ($array->to_be_added_relationship as $key => $value) {
if($value['relationship'] == 'Spouse'){
array_push($array->relationship,['relationship'=>'Spouse','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if($value['relationship'] == 'Child'){
array_push($array->relationship, ['relationship'=>'Son','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
array_push($array->relationship, ['relationship'=>'Daughter','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if($value['relationship'] == 'Parent'){
$Father = array_search('Father',$array->existing_relationship);
$Mother = array_search('Mother',$array->existing_relationship);
if ($Father === false && $Mother === false) {
array_push($array->relationship, ['relationship'=>'Father','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
array_push($array->relationship, ['relationship'=>'Mother','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if ($Father !== false && $Mother === false) {
array_push($array->relationship, ['relationship'=>'Mother','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
} else if ($Mother !== false && $Father === false) {
array_push($array->relationship, ['relationship'=>'Father','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}
}else if($value['relationship'] == 'Parent in law'){
$FatherinLaw = array_search('Father in Law',$array->existing_relationship);
$MotherinLaw = array_search('Mother in Law',$array->existing_relationship);
if ($FatherinLaw === false && $MotherinLaw === false) {
array_push($array->relationship, ['relationship'=>'Father in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
array_push($array->relationship, ['relationship'=>'Mother in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}else if ($FatherinLaw !== false && $MotherinLaw === false) {
array_push($array->relationship, ['relationship'=>'Mother in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
} else if ($MotherinLaw !== false && $FatherinLaw === false) {
array_push($array->relationship, ['relationship'=>'Father in Law','age_validation'=>$value['age_validation'] , 'client_policy_id' => $array->ClientPolicyId]);
}
}
}
@ -2014,6 +2172,10 @@ class EmployeeRestController extends AdminController
$responce['SlabRates'] = is_array($siArray) ? $siArray : $responce['SlabRates'];
$array['to_be_added_relationship'] = [];
$array['existing_relationship'] = [];
// Map family floaters that already exist in the employee table
$familyFloates = $policy_terms->family_floaters;
// remove parent and parent-in-law from familyFloaters
@ -2053,6 +2215,8 @@ class EmployeeRestController extends AdminController
$temp['data']['premium'] = isset($employee_policy->premium) ? $employee_policy->premium : null;
$temp['data']['age_validation'] = $this->getAgeRange($decodedArray,$familyFloatesValue);
array_push($array['existing_relationship'],$temp['data']['relationship']);
array_push($data,$temp);
unset($addOnEmployeeData[$key]);
$floters = array_diff($floters, [$familyFloatesValue]);
@ -2103,6 +2267,7 @@ class EmployeeRestController extends AdminController
$temp2['is_value_exist'] = false;
$temp2['data']['family_floater_key'] = $familyFloatesValue;
$temp2['data']['relationship'] = ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['client_policy_id'] = $array['id'];
$temp2['data']['button_name'] = 'Add '.ucfirst(str_replace('_', ' ', preg_replace('/\d/', '', $familyFloatesValue)));
$temp2['data']['form_type'] = preg_replace('/\d/', '', $familyFloatesValue);
@ -2111,6 +2276,49 @@ class EmployeeRestController extends AdminController
array_push($data,$temp2);
array_push($array['to_be_added_relationship'],['relationship'=>$temp2['data']['relationship'],'age_validation'=>$temp2['data']['age_validation']]);
$array['to_be_added_relationship'] = array_values(
array_map('unserialize',
array_unique(
array_map('serialize', $array['to_be_added_relationship'])
)
)
);
}
}
$responce['relationship'] = [];
foreach ($array['to_be_added_relationship'] as $key => $value) {
if($value['relationship'] == 'Spouse'){
array_push($responce['relationship'],['relationship' => 'Spouse','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
}else if($value['relationship'] == 'Child'){
array_push($responce['relationship'], ['relationship' => 'Son','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
array_push($responce['relationship'], ['relationship' => 'Daughter','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
}else if($value['relationship'] == 'Parent'){
$Father = array_search('Father',$array['existing_relationship']);
$Mother = array_search('Mother',$array['existing_relationship']);
if ($Father === false && $Mother === false) {
array_push($responce['relationship'], ['relationship' => 'Father','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
array_push($responce['relationship'], ['relationship' => 'Mother','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
}else if ($Father !== false && $Mother === false) {
array_push($responce['relationship'], ['relationship' => 'Mother','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
} else if ($Mother !== false && $Father === false) {
array_push($responce['relationship'], ['relationship' => 'Father','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
}
}else if($value['relationship'] == 'Parent in law'){
$FatherinLaw = array_search('Father in Law',$array['existing_relationship']);
$MotherinLaw = array_search('Mother in Law',$array['existing_relationship']);
if ($FatherinLaw === false && $MotherinLaw === false) {
array_push($responce['relationship'], ['relationship' => 'Father in Law','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
array_push($responce['relationship'], ['relationship' => 'Mother in Law','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
}else if ($FatherinLaw !== false && $MotherinLaw === false) {
array_push($responce['relationship'], ['relationship' => 'Mother in Law','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
} else if ($MotherinLaw !== false && $FatherinLaw === false) {
array_push($responce['relationship'], ['relationship' => 'Father in Law','age_validation' => $value['age_validation'],'client_policy_id'=>$array['id']]);
}
}
}
@ -2290,7 +2498,7 @@ class EmployeeRestController extends AdminController
$empData = $this->employeeModel->where('emp_code', $emp_code )->where('client_id', $client_id ) ->where('is_active', 1 )->findAll();
$employeeIds = array_column($empData, 'id');
//for mail common parameter
$filteredEmpData = array_filter($empData, fn($item) => $item['relationship'] === 'Self');
$filteredEmpData = array_values(array_filter($empData, fn($item) => $item['relationship'] === 'Self'));
if (!is_null($client_policy_id) && is_array($client_policy_id))
{
@ -3437,7 +3645,7 @@ class EmployeeRestController extends AdminController
}
public function getPreEmployeePolicyCount()
public function getPreEmployeePolicyCountOld()
{
log_message('error', 'STEP 1: getPreEmployeePolicyCount API called');
@ -3485,6 +3693,7 @@ class EmployeeRestController extends AdminController
->join('client_policy cp', 'employee_polices.client_policy_id = cp.id')
->where('employees.is_active', 1)
->whereIn('employees.emp_status', ['draft', 'enrolled'])
->where('employees.family_floater_key', 'self')
->where('employee_polices.is_active', 1)
->whereIn('employee_polices.status', ['draft', 'enrolled'])
->where('cp.enrolment_visibility', 1)
@ -3521,10 +3730,161 @@ class EmployeeRestController extends AdminController
}
}
public function getPreEmployeePolicyCount()
{
log_message('error', 'STEP 1: getPreEmployeePolicyCount API called');
$request = $this->request->getJSON(true);
$mobile_no = $request['mobile_number'] ?? null;
$email_id = $request['email_id'] ?? null;
$client_short_name = $request['client_short_name'] ?? null;
log_message('error', 'STEP 2: Received input - ' . json_encode($request));
/** ---------------------------------------------------------------
* STEP 3: Resolve Client ID (If client_short_name passed)
* --------------------------------------------------------------- */
$clientId = null;
if (!empty($client_short_name)) {
log_message('error', 'STEP 3: Looking up client with short_name: ' . $client_short_name);
$client = $this->clientModel
->select('id')
->where('is_active', 1)
->where('short_name', $client_short_name)
->first();
if (!empty($client)) {
$clientId = $client['id'];
log_message('error', 'STEP 4: Found client ID: ' . $clientId);
} else {
log_message('error', 'STEP 4: No client found for short_name: ' . $client_short_name);
}
} else {
log_message('error', 'STEP 3: client_short_name is empty.');
}
/** ---------------------------------------------------------------
* STEP 4: Validate Request (either mobile or email is required)
* --------------------------------------------------------------- */
if (empty($mobile_no) && empty($email_id)) {
log_message('error', 'STEP 5: Mobile number and Email both empty. Returning 0.');
return $this->respond(['data' => 0, 'empNotEnrolledCount' => 0]);
}
try {
/** ---------------------------------------------------------------
* STEP 6: Base Query Builder (extract common conditions)
* --------------------------------------------------------------- */
$baseQuery = $this->employeeModel
->join('employee_polices', 'employees.id = employee_polices.employee_id')
->join('client_policy cp', 'employee_polices.client_policy_id = cp.id')
->where('employees.is_active', 1)
->where('employee_polices.is_active', 1)
->where('cp.enrolment_visibility', 1)
->where('cp.open_for_enrollment', 1)
->where('cp.policy_status', 1)
->whereIn('cp.policy_type_id', [1, 2, 3, 6, 7])
->orderBy('employees.created_at', 'desc')
->groupBy('employee_polices.client_policy_id');
// 🔹 Apply Client Filter if Provided
if (!empty($clientId)) {
$baseQuery->where('employees.client_id', $clientId);
log_message('error', 'Applied client ID filter: ' . $clientId);
}
// 🔹 Apply Mobile Filter if Provided
if (!empty($mobile_no)) {
$baseQuery->where('employees.mobile', $mobile_no);
log_message('error', 'Applied mobile_no filter: ' . $mobile_no);
}
// 🔹 Apply Email Filter if Provided
if (!empty($email_id)) {
$baseQuery->where('employees.email_corporate', $email_id);
log_message('error', 'Applied email_id filter: ' . $email_id);
}
/** ---------------------------------------------------------------
* STEP 7: Count Enrolled + Draft (eligible)
* --------------------------------------------------------------- */
$baseQuery->whereIn('employees.emp_status', ['draft', 'enrolled'])
->whereIn('employee_polices.status', ['draft', 'enrolled'])
->where('employees.family_floater_key', 'self');
$count = $baseQuery->get()->getNumRows();
log_message('error', 'Eligible policy count = ' . $count);
/** ---------------------------------------------------------------
* STEP 8: Count Only Draft (Not Enrolled yet)
* --------------------------------------------------------------- */
$notEnrolledQuery = $this->employeeModel
->select("
(
SELECT COUNT(e2.id)
FROM employees AS e2
WHERE e2.is_active = 1
AND e2.emp_status = 'draft'
AND e2.emp_code = employees.emp_code
) AS draft_count
")
->join('employee_polices', 'employees.id = employee_polices.employee_id')
->join('client_policy cp', 'employee_polices.client_policy_id = cp.id')
->where('employees.is_active', 1)
->where('employee_polices.is_active', 1)
->where('cp.enrolment_visibility', 1)
->where('cp.open_for_enrollment', 1)
->where('cp.policy_status', 1)
->whereIn('cp.policy_type_id', [1, 2, 3, 6, 7])
->orderBy('employees.created_at', 'desc');
// 🔹 Apply Client Filter if Provided
if (!empty($clientId)) {
$notEnrolledQuery->where('employees.client_id', $clientId);
log_message('error', 'Applied client ID filter: ' . $clientId);
}
// 🔹 Apply Mobile Filter if Provided
if (!empty($mobile_no)) {
$notEnrolledQuery->where('employees.mobile', $mobile_no);
log_message('error', 'Applied mobile_no filter: ' . $mobile_no);
}
// 🔹 Apply Email Filter if Provided
if (!empty($email_id)) {
$notEnrolledQuery->where('employees.email_corporate', $email_id);
log_message('error', 'Applied email_id filter: ' . $email_id);
}
$notEnrolledQuery->whereIn('employees.emp_status', ['draft'])
->whereIn('employee_polices.status', ['draft']);
$not_enrolled_count = $notEnrolledQuery->get()->getRowArray()['draft_count'] ?? 0;
log_message('error', 'Not enrolled policy count = ' . $not_enrolled_count);
/** ---------------------------------------------------------------
* STEP 9: Final Response
* --------------------------------------------------------------- */
return $this->respond([
'pre_policy_count' => $count,
'emp_not_enrolled_count' => (int) $not_enrolled_count
]);
} catch (\Throwable $e) {
log_message('error', 'Exception occurred: ' . $e->getMessage());
return $this->respond([
'pre_policy_count' => 0,
'emp_not_enrolled_count' => 0
]);
}
}
//--------------------------------------------------------------------------------------------
public function hrFileUpload()
{
try {
@ -3673,4 +4033,107 @@ class EmployeeRestController extends AdminController
}
// copy the active enrolled employee data
public function copyActiveEmployeeAndDependentDetails()
{
$received_payload = $this->request->getGet();
$client_id = $received_payload['client_id'] ?? null;
$emp_code = $received_payload['emp_code'] ?? null;
$new_client_policy_id = $received_payload['new_client_policy_id'] ?? null;
if (empty($client_id)) {
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "client_id is required"], 200);
}
if (empty($new_client_policy_id)) {
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "client_policy_id is required"], 200);
}
if (empty($emp_code)) {
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "emp_code is required"], 200);
}
$client_policy_data = $this->clientPolicyModel
->where('is_active', 1)
->where('client_id', $client_id)
->where('id', $new_client_policy_id)
->whereIn('policy_type_id', [2, 3, 4, 5])
->first();
if (empty($client_policy_data)) {
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "Policy data not found", 'data' => []], 200);
}
$policy_terms = $client_policy_data['policy_terms'] ?? null;
if (empty($policy_terms)) {
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "Policy terms not found", 'data' => []], 200);
}
$policy_terms = json_decode($policy_terms, true);
$family_floaters = $policy_terms['family_floaters'];
$empData = $this->employeeModel
->where('emp_code', $emp_code)
->where('client_id', $client_id)
// ->where('emp_status', 'enrolled')
->where('is_active', 1)
->findAll();
if (empty($empData)) {
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "employee data not found", 'data' => []], 200);
}
$selfData = array_column(
array_filter($empData, function($row) {
return isset($row['relationship']) && strtolower($row['relationship']) == 'self';
}),
'id'
);
$selfId = !empty($selfData) ? reset($selfData) : null;
$floters = $this->FloterConvertion($family_floaters);
$data = [];
foreach ($floters as $familyFloatesValue) {
$dependent = preg_replace('/\d/', '', $familyFloatesValue);
if (count($empData)) {
foreach ($empData as $key => $value) {
if ($value['family_floater_key'] === $dependent) {
$employee_policy = $this->employeePolicyModel->where('employee_id', $selfId)->where('client_policy_id',$new_client_policy_id)->where('is_active', 1 )->get()->getRow();
$temp['is_value_exist'] = true;
$temp['data']['family_floater_key'] = $familyFloatesValue;
$temp['data']['employee_id'] = $value['id'];
$temp['data']['relationship'] = $value['relationship'];
$temp['data']['name'] = $value['name'];
$temp['data']['dob'] = $this->convertDateFormatDMY($value['dob']);
$temp['data']['client_policy_id'] = $new_client_policy_id;
$temp['data']['form_type'] = $dependent;
$temp['data']['basic_cover_si'] = isset($employee_policy->basic_cover_si) ? $employee_policy->basic_cover_si : 0;
$temp['data']['age_validation'] = $this->getAgeRange($policy_terms, $familyFloatesValue);
array_push($data, $temp);
unset($empData[$key]);
$floters = array_diff($floters, [$familyFloatesValue]);
break;
}
}
}
}
if(!empty($data)){
return $this->respond(['status' => "success", 'code' => 200, 'data' => $data], 200);
}else{
return $this->respond(['status' => "failed", 'code' => 404, 'message' => "No data found", 'data' => []], 200);
}
}
}

View File

@ -69,7 +69,10 @@ class RestAuthenticationController extends AdminController
{
$client = \Config\Services::curlrequest();
$url = env('POST_ENROLLMENT_BASEURL').$endPoint;
$response = $client->post( $url, ['json' => $postData, 'http_errors' => false ] );
$headers = [
'App-Signature' => getenv('APP_SIGNATURE'),
];
$response = $client->post( $url, ['json' => $postData, 'headers' => $headers , 'http_errors' => false ] );
// return json_decode($response->getBody(), true);
return $response->getBody();
}
@ -84,15 +87,17 @@ class RestAuthenticationController extends AdminController
$options = [
'query' => $queryParams,
'http_errors' => false,
'headers' => [
'App-Signature' => getenv('APP_SIGNATURE'),
'Accept' => 'application/json'
]
];
if (isset($params['token']) && !empty($params['token'])) {
$options['headers'] = [
'Authorization' => 'Bearer ' . $params['token'],
'Accept' => 'application/json'
];
if (!empty($params['token'])) {
$options['headers']['Authorization'] = 'Bearer ' . $params['token'];
}
$response = $client->get($url, $options);
return $response->getBody();
@ -261,26 +266,63 @@ class RestAuthenticationController extends AdminController
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
// print_r($empdata); die;
$otp = random_int(100000, 999999);
if(empty($empdata)){
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: No employee data found both PRE & POST");
log_message('error', ' ');
log_message('error', '************************ PRE END ********************************');
$retailUserdata = RestAuthHelper::getRetailUserData(['email_id' => $email]);
// print_r($retailUserdata); die;
if (!empty($retailUserdata)) {
$retailApiParams['client_id'] = $retailUserdata['id'];
$retailApiParams['email_id'] = $email;
$retailApiParams['otp'] = $otp;
// update the otp in retail user
$api_response = $this->callThirdPartyAPI($retailApiParams, 'updateRetailUserAuthDetails');
$api_response = json_decode($api_response ?? '{}', true) ?? $api_response;
// print_r($api_response); die;
if (isset($api_response['status']) && $api_response['status'] == true) {
//send Email
$retail_common = [
'client_id' => $retailUserdata['id'],
'client_branch_id' => null,
'client_policy_id' => null,
'employee_policy_id' => null,
'employee_id' => null,
'mail_type' => 'retail_user_otp_mail',
];
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Sending Retail user OTP email to " . $email);
$res = $this->sendEmailOtp($email, $otp, $retail_common);
if (json_decode($res)->status == 'success') {
$result = ['user_verification' => true, 'message' => "Verified Successfully"];
return $this->respond(['status' => 'success', 'code' => 200, 'data' => $result], 200);
} else {
$result = ['user_verification' => false, 'message' => "Mail sending failed , try again"];
return $this->respond(['status' => 'failed', 'code' => 404, 'data' => $result], 200);
}
}
}
$result = ['user_verification' => false , 'message' => "User not found"];
return $this->respond(['status' => 'failed','code' => 404,'data' => $result],200);
}
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: employee data both PRE & POST = " . json_encode($empdata));
$employeeData = [];
if (isset($empdata['pre']) && !empty($empdata['pre'])) {
$employeeData = $empdata['pre'];
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Using PRE data");
}
$otp = random_int(100000, 999999);
if (isset($employeeData['employee_id']))
{
@ -318,7 +360,6 @@ class RestAuthenticationController extends AdminController
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Calling callThirdPartyAPI for updateEmpOTP");
}
//send Email
$common = [
'client_id' => $employeeData['client_id'],
@ -329,11 +370,8 @@ class RestAuthenticationController extends AdminController
'mail_type' => 'otp_mail',
];
$subject = 'Nhance user verification - OTP';
$mail_content = $otp . ' is your verification code for Nhance.';
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Sending OTP email to " . $employeeData['email_corporate']);
$res = MailHelper::send_email(['mail' => $employeeData['email_corporate'], 'subject' => $subject, 'common' => $common, 'message' => $mail_content]);
$res = $this->sendEmailOtp($employeeData['email_corporate'], $otp, $common);
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Mail response = " . $res);
if (json_decode($res)->status == 'success') {
@ -347,6 +385,7 @@ class RestAuthenticationController extends AdminController
$result = ['user_verification' => false, 'message' => "Mail sending failed , try again"];
return $this->respond(['status' => 'failed', 'code' => 404, 'data' => $result], 200);
}
} else {
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: OTP update failed in PRE DATABASE");
log_message('error', ' ');
@ -390,14 +429,37 @@ class RestAuthenticationController extends AdminController
$email_id = isset($this->request->getJSON()->email_id) ? $this->request->getJSON()->email_id : null;
$otp = isset($this->request->getJSON()->otp) ? $this->request->getJSON()->otp : null;
if(empty($otp)){
return $this->respond(['status' => 'OTP is required','code' => 400,'message' => 'OTP is required'], 200);
}
if (empty($mobile_number) && empty($email_id)) {
return $this->respond(['status' => 'failed','code' => 400,'message' => 'Mobile number or Email ID is required'], 200);
}
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - getVerifiedUserData: Fetching empdata via RestAuthHelper");
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email_id, 'otp' => $otp, 'mobile_number' => $mobile_number ]);
if(empty($empdata)){
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - getVerifiedUserData: empdata is empty");
log_message('error', ' ');
log_message('error', '************************ PRE END ********************************');
$retailUserdata = RestAuthHelper::getRetailUserData(['email_id' => $email_id, 'mobile_number' => $mobile_number, 'otp' => $otp]);
// print_r($retailUserdata); die;
if (!empty($retailUserdata)) {
$retailApiParams['client_id'] = $retailUserdata['id'];
$retailApiParams['email_id'] = $email_id;
$retailApiParams['mobile_number'] = $mobile_number;
$retailApiParams['otp'] = $otp;
// Call the third-party API function
$apiResponse = $this->callThirdPartyAPI($retailApiParams, 'getVerifiedRetailUserData');
// print_r($apiResponse); die;
return $this->respond(['status' => 'failed', 'code' => 200, 'data' => [], 'post_enrollment' => json_decode($apiResponse, true)], 200);
}
return $this->respond(['status' => 'Invalid OTP','code' => 404,'data' => "", 'message' => "Invalid OTP"],200);
}
@ -473,6 +535,15 @@ class RestAuthenticationController extends AdminController
// employee auth api's end
public function sendEmailOtp($email, $otp, $common)
{
$subject = 'Nhance user verification - OTP';
$mail_content = $otp . ' is your verification code for Nhance.';
$response = MailHelper::send_email(['mail' => $email, 'subject' => $subject, 'common' => $common, 'message' => $mail_content]);
return $response;
}

View File

@ -20,7 +20,7 @@ class AuthJWT implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
$jwt = $request->getHeader('Authorization');
$jwt = $request->getHeaderLine('Authorization');
if ($jwt) {
if (JWTToken::validateJWT($jwt)) {

422
app/Filters/Cors.php Normal file
View File

@ -0,0 +1,422 @@
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
/**
* CORS (Cross-Origin Resource Sharing) Filter
*
* Handles CORS preflight requests and adds appropriate CORS headers to responses.
* Configurable via environment variables for flexibility across different environments.
*
* @package App\Filters
*/
class Cors implements FilterInterface
{
/**
* List of allowed origins (domains that can access this API)
* Can include wildcards like *.example.com
*
* @var array<string>
*/
protected array $allowedOrigins = [];
/**
* Whether to allow credentials (cookies, authorization headers) in CORS requests
* WARNING: Cannot be true if using wildcard (*) origin
*
* @var bool
*/
protected bool $allowCredentials = false;
/**
* HTTP methods allowed for CORS requests
*
* @var string
*/
protected string $allowedMethods = 'GET,POST,PUT,PATCH,DELETE,OPTIONS';
/**
* HTTP headers allowed in CORS requests
*
* @var string
*/
protected string $allowedHeaders = 'Content-Type,Authorization,X-Requested-With,Accept,Origin';
/**
* Headers exposed to the client (accessible via JavaScript)
*
* @var string
*/
protected string $exposeHeaders = '';
/**
* How long (in seconds) the preflight response can be cached
* Default: 24 hours (86400 seconds)
*
* @var int
*/
protected int $maxAge = 86400;
/**
* Whether to enable debug logging for CORS requests
*
* @var bool
*/
protected bool $debug = false;
/**
* Initialize CORS configuration from environment variables
*
* @throws \RuntimeException If configuration is invalid
*/
protected $myLogger;
public function __construct()
{
$this->myLogger = \Config\Services::mylogger();
// Parse allowed origins from environment variable
// Format: comma or semicolon separated list
// Examples: "https://example.com,https://app.example.com" or "*.example.com"
$raw = env('CORS_ALLOWED_ORIGINS', '*');
$parts = preg_split('/\s*[,;]\s*/', trim($raw));
$this->allowedOrigins = array_filter(array_map('trim', $parts));
// Load other configuration from environment
$this->allowCredentials = filter_var(
env('CORS_ALLOW_CREDENTIALS', false),
FILTER_VALIDATE_BOOLEAN
);
$this->allowedMethods = env('CORS_ALLOWED_METHODS', $this->allowedMethods);
$this->allowedHeaders = env('CORS_ALLOWED_HEADERS', $this->allowedHeaders);
$this->exposeHeaders = env('CORS_EXPOSE_HEADERS', $this->exposeHeaders);
$this->maxAge = (int) env('CORS_MAX_AGE', $this->maxAge);
$this->debug = filter_var(env('CORS_DEBUG', false), FILTER_VALIDATE_BOOLEAN);
// Security validation: wildcard origin cannot be used with credentials
// This is a browser security requirement, not just a best practice
if ($this->allowCredentials && in_array('*', $this->allowedOrigins, true)) {
throw new \RuntimeException(
'CORS configuration error: Cannot use wildcard (*) origin with credentials enabled. ' .
'This violates browser security policies. Either disable credentials or specify explicit origins.'
);
}
$this->log('CORS filter initialized', [
'allowed_origins' => $this->allowedOrigins,
'allow_credentials' => $this->allowCredentials,
'allowed_methods' => $this->allowedMethods,
]);
}
/**
* Check if a given origin is allowed to access this API
*
* Supports:
* - Exact matches: https://example.com
* - Wildcard origins: *.example.com
* - Scheme-less matching: example.com (matches http and https)
* - Universal wildcard: *
*
* @param string|null $origin The Origin header from the request
* @return bool True if origin is allowed, false otherwise
*/
protected function isOriginAllowed(?string $origin): bool
{
// Reject empty origins
if (empty($origin)) {
$this->log('Origin rejected: empty origin header');
return false;
}
// Validate origin format - must include scheme (http:// or https://)
// This prevents malformed origins from being accepted
if (!preg_match('#^https?://#i', $origin)) {
$this->log('Origin rejected: invalid format (missing scheme)', ['origin' => $origin]);
return false;
}
// If wildcard present in configuration, allow any origin
if (in_array('*', $this->allowedOrigins, true)) {
$this->log('Origin allowed: wildcard match', ['origin' => $origin]);
return true;
}
// Parse the host from the origin for wildcard matching
// Example: https://app.example.com:8080 → app.example.com
$originHost = parse_url($origin, PHP_URL_HOST) ?: $origin;
foreach ($this->allowedOrigins as $allowed) {
if ($allowed === '') {
continue;
}
// 1. Exact match (including scheme and port)
// Example: https://example.com matches https://example.com
if (strcasecmp($allowed, $origin) === 0) {
$this->log('Origin allowed: exact match', [
'origin' => $origin,
'matched_rule' => $allowed
]);
return true;
}
// 2. Handle scheme-less and wildcard patterns
// If the allowed entry doesn't contain ://, it's either a host-only or wildcard pattern
if (strpos($allowed, '://') === false) {
// 2a. Wildcard subdomain pattern: *.example.com
// Matches: app.example.com, api.example.com, dev.app.example.com
// Does NOT match: example.com (use explicit entry for root domain)
if (strpos($allowed, '*.') === 0) {
$allowedRoot = substr($allowed, 2); // Remove *. prefix
// Check if origin host ends with the allowed root domain
if ($originHost === $allowedRoot || str_ends_with($originHost, '.' . $allowedRoot)) {
$this->log('Origin allowed: wildcard subdomain match', [
'origin' => $origin,
'matched_rule' => $allowed,
'origin_host' => $originHost
]);
return true;
}
}
// 2b. Direct host match (scheme-less)
// Allows both http and https for the same host
// Example: example.com matches both http://example.com and https://example.com
else {
if (strcasecmp($allowed, $originHost) === 0) {
$this->log('Origin allowed: host match (scheme-less)', [
'origin' => $origin,
'matched_rule' => $allowed,
'origin_host' => $originHost
]);
return true;
}
}
}
}
// No match found - reject this origin
$this->log('Origin rejected: no matching rule', [
'origin' => $origin,
'checked_rules' => $this->allowedOrigins
]);
return false;
}
/**
* Build the Access-Control-Allow-Origin header value
*
* Returns either:
* - '*' if wildcard is configured and credentials are disabled
* - The actual origin value if credentials are enabled or specific origins configured
*
* Note: When credentials are enabled, you MUST echo back the specific origin,
* browsers reject wildcard with credentials.
*
* @param string $origin The validated origin
* @return string The value for Access-Control-Allow-Origin header
*/
protected function buildAllowOriginHeader(string $origin): string
{
// If wildcard configured and credentials NOT required, can safely return '*'
// This allows any origin to access the resource
if (in_array('*', $this->allowedOrigins, true) && !$this->allowCredentials) {
return '*';
}
// Otherwise, must return the specific origin
// This is required when allow-credentials is true
return $origin;
}
/**
* Add all CORS headers to the response
*
* This method is called for both preflight and actual requests
* to ensure consistent CORS headers across all responses.
*
* @param ResponseInterface $response The response object to add headers to
* @param RequestInterface $request The original request
* @param string $origin The validated origin
* @param bool $isPreflight Whether this is a preflight OPTIONS request
* @return void
*/
protected function addCorsHeaders(
ResponseInterface $response,
RequestInterface $request,
string $origin,
bool $isPreflight = false
): void {
// CRITICAL: Vary header prevents caching issues
// Without this, a cached response for origin A might be served to origin B,
// causing CORS errors because the Access-Control-Allow-Origin won't match
$response->setHeader('Vary', 'Origin');
// Set the allowed origin
$allowOrigin = $this->buildAllowOriginHeader($origin);
$response->setHeader('Access-Control-Allow-Origin', $allowOrigin);
// If credentials are allowed, set the header
// This allows cookies, authorization headers, and TLS client certificates
if ($this->allowCredentials) {
$response->setHeader('Access-Control-Allow-Credentials', 'true');
}
// Allowed HTTP methods
$response->setHeader('Access-Control-Allow-Methods', $this->allowedMethods);
// Handle allowed headers
if ($isPreflight) {
// For preflight: respect what the browser is asking for
// The browser sends Access-Control-Request-Headers to ask permission
$requestedHeaders = $request->getHeaderLine('Access-Control-Request-Headers');
$response->setHeader(
'Access-Control-Allow-Headers',
$requestedHeaders ?: $this->allowedHeaders
);
} else {
// For actual requests: use configured headers
// Access-Control-Request-Headers is only for preflight
$response->setHeader('Access-Control-Allow-Headers', $this->allowedHeaders);
}
// Expose additional headers to the client (accessible via JavaScript)
// Without this, only simple headers are accessible: Cache-Control, Content-Language,
// Content-Type, Expires, Last-Modified, Pragma
if (!empty($this->exposeHeaders)) {
$response->setHeader('Access-Control-Expose-Headers', $this->exposeHeaders);
}
// Cache duration for preflight responses
// Reduces preflight requests by allowing browser to cache the permissions
if ($this->maxAge > 0) {
$response->setHeader('Access-Control-Max-Age', (string) $this->maxAge);
}
}
/**
* Execute before the controller
*
* Handles preflight OPTIONS requests by returning early with appropriate headers.
* For other requests, allows them to proceed to the controller.
*
* @param RequestInterface $request The request object
* @param mixed $arguments Optional arguments
* @return ResponseInterface|null Response for preflight, null for other requests
*/
public function before(RequestInterface $request, $arguments = null)
{
$origin = $request->getHeaderLine('Origin') ?: '';
$method = strtoupper($request->getMethod());
// Handle preflight OPTIONS requests
// Preflight is sent by browsers before actual cross-origin requests
// to check if the actual request is safe to send
if ($method === 'OPTIONS') {
$this->log('Preflight request received', [
'origin' => $origin,
'method' => $method,
'uri' => (string) $request->getUri()
]);
// Validate origin - reject if not allowed
if (empty($origin) || !$this->isOriginAllowed($origin)) {
$this->log('Preflight rejected: origin not allowed', ['origin' => $origin]);
// Return 403 Forbidden for rejected origins
// Some prefer 200 with no CORS headers, but 403 is more explicit
return Services::response()
->setStatusCode(403)
->setJSON(['error' => 'Origin not allowed']);
}
// Origin is valid - build preflight response
$response = Services::response();
$this->addCorsHeaders($response, $request, $origin, true);
// 204 No Content is the standard response for successful preflight
// It indicates "permission granted, but no data to return"
$response->setStatusCode(204);
$response->setBody('');
$this->log('Preflight approved', [
'origin' => $origin,
'allowed_methods' => $this->allowedMethods
]);
return $response;
}
// For non-OPTIONS requests, don't return a response
// Let the request proceed to the controller
// CORS headers will be added in after() method
return null;
}
/**
* Execute after the controller
*
* Adds CORS headers to the response for actual (non-preflight) requests.
* This ensures all API responses include proper CORS headers.
*
* @param RequestInterface $request The request object
* @param ResponseInterface $response The response object
* @param mixed $arguments Optional arguments
* @return void
*/
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
$origin = $request->getHeaderLine('Origin') ?: '';
// Only add CORS headers if origin is present and allowed
// No origin header means it's a same-origin request (no CORS needed)
if (empty($origin)) {
return;
}
if (!$this->isOriginAllowed($origin)) {
$this->log('Response blocked: origin not allowed', [
'origin' => $origin,
'uri' => (string) $request->getUri()
]);
return;
}
// Add CORS headers to the response
$this->addCorsHeaders($response, $request, $origin, false);
$this->log('CORS headers added to response', [
'origin' => $origin,
'status' => $response->getStatusCode()
]);
}
/**
* Log debug information if debug mode is enabled
*
* Logs to CodeIgniter's log system at 'info' level.
* Enable with CORS_DEBUG=true in .env file.
*
* @param string $message The log message
* @param array $context Additional context data
* @return void
*/
protected function log(string $message, array $context = []): void
{
if (!$this->debug) {
return;
}
// $logger = Services::logger();
$contextString = !empty($context) ? json_encode($context, JSON_UNESCAPED_SLASHES) : '';
$this->myLogger->logme('error','[CORS] ' . $message . ($contextString ? ' | ' . $contextString : ''));
// $logger->info('[CORS] ' . $message . ($contextString ? ' | ' . $contextString : ''));
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class VerifyAppSignature implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
// Get the header sent by the Flutter app
$clientSignature = $request->getHeaderLine('App-Signature');
// Load the server's expected signature from the .env
$validSignature = getenv('APP_SIGNATURE');
// Check if signature is valid
if ($clientSignature !== $validSignature) {
return service('response')
->setStatusCode(403)
->setJSON([
'status' => false,
'message' => 'Forbidden: Invalid App Signature',
]);
}
// allow request to proceed
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// nothing to do after response
}
}

View File

@ -346,6 +346,9 @@ class RestAuthHelper
$client = \Config\Services::curlrequest();
$endPoint = 'getPostEmployeeDataForAuth';
$url = env('POST_ENROLLMENT_BASEURL') . $endPoint;
$headers = [
'App-Signature' => getenv('APP_SIGNATURE'),
];
$postData = [];
@ -368,7 +371,7 @@ class RestAuthHelper
log_message('error', 'Sending POST to external API: ' . $url);
log_message('error', 'POST payload: ' . json_encode($postData));
$response = $client->post($url, ['json' => $postData, 'http_errors' => false]);
$response = $client->post($url, ['json' => $postData, 'headers' => $headers , 'http_errors' => false]);
$post_json = $response->getBody();
// log_message('error', 'Response from API: ' . $post_json);
@ -380,7 +383,7 @@ class RestAuthHelper
return $data;
}
log_message('warning', 'No mobile or email present in params for post fetch.');
log_message('error', 'No mobile or email present in params for post fetch.');
}
public static function updatePreMpin(array $params)
@ -437,4 +440,60 @@ class RestAuthHelper
log_message('warning', '[updatePostMpin] Missing required parameters: employee_id or mpin');
return false;
}
// ----------------------------------------------------------------------------------------------
public static function getRetailUserData(array $params)
{
log_message('error', 'Function getRetailUserData called with: ' . json_encode($params));
$mobile_number = $params['mobile_number'] ?? null;
$email_id = $params['email_id'] ?? null;
$otp = $params['otp'] ?? null;
$old_mpin = $params['old_mpin'] ?? null;
if (!empty($mobile_number) || !empty($email_id)) {
$client = \Config\Services::curlrequest();
$endPoint = 'getRetailUserData';
$url = env('POST_ENROLLMENT_BASEURL') . $endPoint;
$headers = [
'App-Signature' => getenv('APP_SIGNATURE'),
];
$postData = [];
if (!empty($mobile_number)) {
$postData['mobile_number'] = $mobile_number;
}
if (!empty($email_id)) {
$postData['email_id'] = $email_id;
}
if (!empty($otp)) {
$postData['otp'] = $otp;
}
if (!empty($old_mpin)) {
$postData['old_mpin'] = $old_mpin;
}
log_message('error', 'Sending POST to external API: ' . $url);
log_message('error', 'POST payload: ' . json_encode($postData));
$response = $client->post($url, ['json' => $postData, 'headers' => $headers, 'http_errors' => false]);
$post_json = $response->getBody();
// print_r($post_json);
$post_data = json_decode($post_json, true);
$data = $post_data['data'] ?? [];
log_message('error', 'Parsed post_data: ' . json_encode($data));
return $data;
}
return [];
}
}

View File

@ -666,3 +666,35 @@ if (!function_exists('check_pay_by_employee_or_company')) {
}
if (!function_exists('getLatestGMCPolicy')) {
function getLatestGMCPolicy(array $empPolicy)
{
try{
$filtered = array_filter($empPolicy, function ($row) {
$type = is_object($row) ? $row->policy_type_id : $row['policy_type_id'];
return isset($type) && (int)$type === 2;
});
if (count($filtered) > 1) {
usort($filtered, function ($a, $b) {
$dateA = is_object($a) ? $a->policy_end_date : $a['policy_end_date'];
$dateB = is_object($b) ? $b->policy_end_date : $b['policy_end_date'];
return strtotime($dateB) <=> strtotime($dateA);
});
$row = reset($filtered);
return is_object($row) ? ($row->ClientPolicyId ?? null) : ($row['ClientPolicyId'] ?? null);
}
return null;
}catch(\Exception $e){
log_message('error', 'Exception getLatestGMCPolicy :' . $e->getMessage());
return null;
}
}
}

View File

@ -166,7 +166,8 @@ class EmployeeModel extends Model
client_policy.disclaimer,
client_policy.policy_type_id ,
employee_polices.tpa_id as tpa_id ,
employee_polices.rand_string as rand_string
employee_polices.rand_string as rand_string,
client_policy.policy_end_date
', FALSE) // Select all columns from both tables
->join('client_policy', 'client_policy.id = employee_polices.client_policy_id')
->join('policy_type', 'policy_type.id = client_policy.policy_type_id')

View File

@ -60,8 +60,71 @@
#table-client-policy_filter{
text-align: left;
}
</style>
<style>
.switch {
position: relative;
display: inline-block;
width: 54px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 19px;
width: 19px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
</style>
<div class="tab-pane fade" id="police-tab">
@ -227,7 +290,7 @@
required>
</div>
<div class="form-group col-md-4">
<!-- <div class="form-group col-md-4">
<label class="switch" style="position: relative;top: 43px;left: 20px;">
<input id="inception_type" type="checkbox" name="inception_type">
<span class="slider round" style="height: 27px;"></span>
@ -235,6 +298,15 @@
<label for="inception_type" style="position: relative;bottom: 5px;left: 85px;">Enable
Employee Enrolment Process</label>
</div> -->
<div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<label for="inception_type" style=" position: relative;bottom: 5px;">
<label class="switch">
<input id="inception_type" type="checkbox" name="inception_type">
<span class="slider round" style="height: 27px;"></span>
</label>Enable
Employee Enrolment Process
</label>
</div>
<div class="form-row">
<div class="form-group col-md-4">
@ -262,14 +334,25 @@
id="disclaimer"></textarea>
</div>
<div class="form-group col-md-4">
<div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<label for="policy_visibility" style=" position: relative;bottom: 5px;">
<label class="switch">
<!-- <input id="policy_visibility" type="checkbox" name="policy_visibility" checked > -->
<input id="policy_visibility" type="checkbox" name="enrolment_visibility" checked>
<span class="slider round" style="height: 27px;"></span>
</label>
Policy Visibilty in Enrollment App
</label>
</div>
<!-- <div class="form-group col-md-4">
<label class="switch" style="position: relative;top: 43px;left: 20px;">
<input id="policy_visibility" type="checkbox" name="enrolment_visibility" checked>
<span class="slider round" style="height: 27px;"></span>
</label>
<label for="policy_visibility" style="position: relative;bottom: 5px;left: 85px;">Policy Visibilty in Enrollment App</label>
</div>
</div> -->
<!-- <div class="form-group col-md-4">
<label class="switch" style="position: relative;top: 43px;left: 20px;">
@ -280,7 +363,7 @@
<label for="is_member_modify_allowed" style="position: relative;bottom: 5px;left: 85px;"> In Enrollment Member Data Modification Allowed</label>
</div> -->
<div class="form-group col-md-4">
<!-- <div class="form-group col-md-4">
<label class="switch" style="position: relative;top: 43px;left: 20px;">
<input id="is_lgbtq" type="checkbox" name="is_lgbtq">
<span class="slider round" style="height: 27px;"></span>
@ -296,6 +379,23 @@
</label>
<label for="is_premium_summery" style="position: relative;bottom: 5px;left: 85px;"> Is Premium Summary Display Enabled </label>
</div> -->
<div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<label for="is_lgbtq" style=" position: relative;bottom: 5px;">
<label class="switch">
<input id="is_lgbtq" type="checkbox" name="is_lgbtq" checked >
<span class="slider round" style="height: 27px;"></span>
</label>
Is LGBTQ Enable</label>
</div>
<div class="form-group col-md-4" style="padding-top:50px;padding-bottom: 0px;">
<label for="is_premium_summery" style=" position: relative;bottom: 5px;">
<label class="switch">
<input id="is_premium_summery" type="checkbox" name="is_premium_summery" checked>
<span class="slider round" style="height: 27px;"></span>
</label>
Is Premium Summary Display Enabled </label>
</div>
</div>

76
ca.pem Normal file
View File

@ -0,0 +1,76 @@
-----BEGIN CERTIFICATE-----
MIIEADCCAuigAwIBAgIQB/57HSuaqUkLaasdjxUdPjANBgkqhkiG9w0BAQsFADCB
mDELMAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIElu
Yy4xEzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTEwLwYDVQQDDChB
bWF6b24gUkRTIGFwLXNvdXRoLTEgUm9vdCBDQSBSU0EyMDQ4IEcxMRAwDgYDVQQH
DAdTZWF0dGxlMCAXDTIxMDUxOTE3NDAzNFoYDzIwNjEwNTE5MTg0MDM0WjCBmDEL
MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x
EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTEwLwYDVQQDDChBbWF6
b24gUkRTIGFwLXNvdXRoLTEgUm9vdCBDQSBSU0EyMDQ4IEcxMRAwDgYDVQQHDAdT
ZWF0dGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbkaoVsUS76o
TgLFmcnaB8cswBk1M3Bf4IVRcwWT3a1HeJSnaJUqWHCJ+u3ip/zGVOYl0gN1MgBb
MuQRIJiB95zGVcIa6HZtx00VezDTr3jgGWRHmRjNVCCHGmxOZWvJjsIE1xavT/1j
QYV/ph4EZEIZ/qPq7e3rHohJaHDe23Z7QM9kbyqp2hANG2JtU/iUhCxqgqUHNozV
Zd0l5K6KnltZQoBhhekKgyiHqdTrH8fWajYl5seD71bs0Axowb+Oh0rwmrws3Db2
Dh+oc2PwREnjHeca9/1C6J2vhY+V0LGaJmnnIuOANrslx2+bgMlyhf9j0Bv8AwSi
dSWsobOhNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQb7vJT
VciLN72yJGhaRKLn6Krn2TAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
ggEBAAxEj8N9GslReAQnNOBpGl8SLgCMTejQ6AW/bapQvzxrZrfVOZOYwp/5oV0f
9S1jcGysDM+DrmfUJNzWxq2Y586R94WtpH4UpJDGqZp+FuOVJL313te4609kopzO
lDdmd+8z61+0Au93wB1rMiEfnIMkOEyt7D2eTFJfJRKNmnPrd8RjimRDlFgcLWJA
3E8wca67Lz/G0eAeLhRHIXv429y8RRXDtKNNz0wA2RwURWIxyPjn1fHjA9SPDkeW
E1Bq7gZj+tBnrqz+ra3yjZ2blss6Ds3/uRY6NYqseFTZWmQWT7FolZEnT9vMUitW
I0VynUbShVpGf6946e0vgaaKw20=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICrjCCAjWgAwIBAgIQGKVv+5VuzEZEBzJ+bVfx2zAKBggqhkjOPQQDAzCBlzEL
MAkGA1UEBhMCVVMxIjAgBgNVBAoMGUFtYXpvbiBXZWIgU2VydmljZXMsIEluYy4x
EzARBgNVBAsMCkFtYXpvbiBSRFMxCzAJBgNVBAgMAldBMTAwLgYDVQQDDCdBbWF6
b24gUkRTIGFwLXNvdXRoLTEgUm9vdCBDQSBFQ0MzODQgRzExEDAOBgNVBAcMB1Nl
YXR0bGUwIBcNMjEwNTE5MTc1MDU5WhgPMjEyMTA1MTkxODUwNTlaMIGXMQswCQYD
VQQGEwJVUzEiMCAGA1UECgwZQW1hem9uIFdlYiBTZXJ2aWNlcywgSW5jLjETMBEG
A1UECwwKQW1hem9uIFJEUzELMAkGA1UECAwCV0ExMDAuBgNVBAMMJ0FtYXpvbiBS
RFMgYXAtc291dGgtMSBSb290IENBIEVDQzM4NCBHMTEQMA4GA1UEBwwHU2VhdHRs
ZTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMqdLJ0tZF/DGFZTKZDrGRJZID8ivC2I
JRCYTWweZKCKSCAzoiuGGHzJhr5RlLHQf/QgmFcgXsdmO2n3CggzhA4tOD9Ip7Lk
P05eHd2UPInyPCHRgmGjGb0Z+RdQ6zkitKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAd
BgNVHQ4EFgQUC1yhRgVqU5bR8cGzOUCIxRpl4EYwDgYDVR0PAQH/BAQDAgGGMAoG
CCqGSM49BAMDA2cAMGQCMG0c/zLGECRPzGKJvYCkpFTCUvdP4J74YP0v/dPvKojL
t/BrR1Tg4xlfhaib7hPc7wIwFvgqHes20CubQnZmswbTKLUrgSUW4/lcKFpouFd2
t2/ewfi/0VhkeUW+IiHhOMdU
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIGATCCA+mgAwIBAgIRAKlQ+3JX9yHXyjP/Ja6kZhkwDQYJKoZIhvcNAQEMBQAw
gZgxCzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ
bmMuMRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTExMC8GA1UEAwwo
QW1hem9uIFJEUyBhcC1zb3V0aC0xIFJvb3QgQ0EgUlNBNDA5NiBHMTEQMA4GA1UE
BwwHU2VhdHRsZTAgFw0yMTA1MTkxNzQ1MjBaGA8yMTIxMDUxOTE4NDUyMFowgZgx
CzAJBgNVBAYTAlVTMSIwIAYDVQQKDBlBbWF6b24gV2ViIFNlcnZpY2VzLCBJbmMu
MRMwEQYDVQQLDApBbWF6b24gUkRTMQswCQYDVQQIDAJXQTExMC8GA1UEAwwoQW1h
em9uIFJEUyBhcC1zb3V0aC0xIFJvb3QgQ0EgUlNBNDA5NiBHMTEQMA4GA1UEBwwH
U2VhdHRsZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKtahBrpUjQ6
H2mni05BAKU6Z5USPZeSKmBBJN3YgD17rJ93ikJxSgzJ+CupGy5rvYQ0xznJyiV0
91QeQN4P+G2MjGQR0RGeUuZcfcZitJro7iAg3UBvw8WIGkcDUg+MGVpRv/B7ry88
7E4OxKb8CPNoa+a9j6ABjOaaxaI22Bb7j3OJ+JyMICs6CU2bgkJaj3VUV9FCNUOc
h9PxD4jzT9yyGYm/sK9BAT1WOTPG8XQUkpcFqy/IerZDfiQkf1koiSd4s5VhBkUn
aQHOdri/stldT7a+HJFVyz2AXDGPDj+UBMOuLq0K6GAT6ThpkXCb2RIf4mdTy7ox
N5BaJ+ih+Ro3ZwPkok60egnt/RN98jgbm+WstgjJWuLqSNInnMUgkuqjyBWwePqX
Kib+wdpyx/LOzhKPEFpeMIvHQ3A0sjlulIjnh+j+itezD+dp0UNxMERlW4Bn/IlS
sYQVNfYutWkRPRLErXOZXtlxxkI98JWQtLjvGzQr+jywxTiw644FSLWdhKa6DtfU
2JWBHqQPJicMElfZpmfaHZjtXuCZNdZQXWg7onZYohe281ZrdFPOqC4rUq7gYamL
T+ZB+2P+YCPOLJ60bj/XSvcB7mesAdg8P0DNddPhHUFWx2dFqOs1HxIVB4FZVA9U
Ppbv4a484yxjTgG7zFZNqXHKTqze6rBBAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
Af8wHQYDVR0OBBYEFCEAqjighncv/UnWzBjqu1Ka2Yb4MA4GA1UdDwEB/wQEAwIB
hjANBgkqhkiG9w0BAQwFAAOCAgEAYyvumblckIXlohzi3QiShkZhqFzZultbFIu9
GhA5CDar1IFMhJ9vJpO9nUK/camKs1VQRs8ZsBbXa0GFUM2p8y2cgUfLwFULAiC/
sWETyW5lcX/xc4Pyf6dONhqFJt/ovVBxNZtcmMEWv/1D6Tf0nLeEb0P2i/pnSRR4
Oq99LVFjossXtyvtaq06OSiUUZ1zLPvV6AQINg8dWeBOWRcQYhYcEcC2wQ06KShZ
0ahuu7ar5Gym3vuLK6nH+eQrkUievVomN/LpASrYhK32joQ5ypIJej3sICIgJUEP
UoeswJ+Z16f3ECoL1OSnq4A0riiLj1ZGmVHNhM6m/gotKaHNMxsK9zsbqmuU6IT/
P6cR0S+vdigQG8ZNFf5vEyVNXhl8KcaJn6lMD/gMB2rY0qpaeTg4gPfU5wcg8S4Y
C9V//tw3hv0f2n+8kGNmqZrylOQDQWSSo8j8M2SRSXiwOHDoTASd1fyBEIqBAwzn
LvXVg8wQd1WlmM3b0Vrsbzltyh6y4SuKSkmgufYYvC07NknQO5vqvZcNoYbLNea3
76NkFaMHUekSbwVejZgG5HGwbaYBgNdJEdpbWlA3X4yGRVxknQSUyt4dZRnw/HrX
k8x6/wvtw7wht0/DOqz1li7baSsMazqxx+jDdSr1h9xML416Q4loFCLgqQhil8Jq
Em4Hy3A=
-----END CERTIFICATE-----