Skip to content

Commit

Permalink
Security configuration enhancements in the application (#1208)
Browse files Browse the repository at this point in the history
  • Loading branch information
alextselegidis committed May 10, 2022
1 parent 886343f commit 384d442
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 19 deletions.
2 changes: 1 addition & 1 deletion application/config/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
| $autoload['helper'] = array('url', 'file');
*/

$autoload['helper'] = ['custom_exceptions', 'url', 'file', 'language', 'asset', 'config', 'render'];
$autoload['helper'] = ['custom_exceptions', 'url', 'file', 'language', 'asset', 'config', 'render', 'rate_limit', 'security'];


/*
Expand Down
13 changes: 12 additions & 1 deletion application/config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@
$config['cookie_prefix'] = "";
$config['cookie_domain'] = "";
$config['cookie_path'] = "/";
$config['cookie_secure'] = FALSE;
$config['cookie_secure'] = strpos($config['base_url'], 'https') !== FALSE;

/*
|--------------------------------------------------------------------------
Expand Down Expand Up @@ -457,6 +457,17 @@
*/
$config['proxy_ips'] = '';

/*
|--------------------------------------------------------------------------
| Rate Limiting
|--------------------------------------------------------------------------
|
| Toggle the rate limiting feature in your application. Using rate limiting
| will control the number of requests a client can sent to the app.
|
*/
$config['rate_limiting'] = TRUE;


/* End of file config.php */
/* Location: ./application/config/config.php */
82 changes: 75 additions & 7 deletions application/controllers/Appointments.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,23 @@ public function index($appointment_hash = '')
$available_providers[$index] = $stripped_data;
}

// Remove the data that are not needed inside the $available_services array.
foreach ($available_services as $index => $service)
{
$stripped_data = [
'id' => $service['id'],
'name' => $service['name'],
'duration' => $service['duration'],
'location' => $service['location'],
'price' => $service['price'],
'currency' => $service['currency'],
'description' => $service['description'],
'category_id' => $service['category_id'],
'category_name' => $service['category_name']
];
$available_services[$index] = $stripped_data;
}

// If an appointment hash is provided then it means that the customer is trying to edit a registered
// appointment record.
if ($appointment_hash !== '')
Expand Down Expand Up @@ -133,9 +150,40 @@ public function index($appointment_hash = '')
}

$appointment = $results[0];

$appointment = [
'id' => $appointment['id'],
'hash' => $appointment['hash'],
'start_datetime' => $appointment['start_datetime'],
'end_datetime' => $appointment['end_datetime'],
'id_services' => $appointment['id_services'],
'id_users_customer' => $appointment['id_users_customer'],
'id_users_provider' => $appointment['id_users_provider'],
'notes' => $appointment['notes']
];

$provider = $this->providers_model->get_row($appointment['id_users_provider']);

$provider = [
'id' => $provider['id'],
'first_name' => $provider['first_name'],
'last_name' => $provider['last_name'],
'services' => $provider['services'],
'timezone' => $provider['timezone']
];

$customer = $this->customers_model->get_row($appointment['id_users_customer']);

$customer = [
'id' => $customer['id'],
'first_name' => $customer['first_name'],
'last_name' => $customer['last_name'],
'timezone' => $customer['timezone'],
'address' => $customer['address'],
'city' => $customer['city'],
'zip_code' => $customer['zip_code']
];

$customer_token = md5(uniqid(mt_rand(), TRUE));

// Save the token for 10 minutes.
Expand Down Expand Up @@ -197,6 +245,13 @@ public function cancel($appointment_hash)
{
try
{
$cancel_reason = $this->input->post('cancel_reason');

if ($this->input->method() !== 'post' || empty($cancel_reason))
{
show_error('Bad Request', 400);
}

// Check whether the appointment hash exists in the database.
$appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]);

Expand Down Expand Up @@ -279,22 +334,25 @@ public function book_success($appointment_hash)
$exceptions = $this->session->flashdata('book_success');

$view = [
'appointment_data' => $appointment,
'appointment_data' => [
'start_datetime' => $appointment['start_datetime'],
'end_datetime' => $appointment['end_datetime'],
],
'provider_data' => [
'id' => $provider['id'],
'first_name' => $provider['first_name'],
'last_name' => $provider['last_name'],
'email' => $provider['email'],
'timezone' => $provider['timezone'],
],
'customer_data' => [
'id' => $customer['id'],
'first_name' => $customer['first_name'],
'last_name' => $customer['last_name'],
'email' => $customer['email'],
'timezone' => $customer['timezone'],
],
'service_data' => $service,
'service_data' => [
'name' => $service['name'],
],
'company_name' => $company_name,
];

Expand Down Expand Up @@ -386,7 +444,7 @@ public function ajax_get_available_hours()
*
* @throws Exception
*/
protected function search_any_provider($service_id, $date, $hour = null)
protected function search_any_provider($service_id, $date, $hour = NULL)
{
$available_providers = $this->providers_model->get_available_providers();

Expand All @@ -405,7 +463,7 @@ protected function search_any_provider($service_id, $date, $hour = null)
// Check if the provider is available for the requested date.
$available_hours = $this->availability->get_available_hours($date, $service, $provider);

if (count($available_hours) > $max_hours_count && (empty($hour) || in_array($hour, $available_hours, false)))
if (count($available_hours) > $max_hours_count && (empty($hour) || in_array($hour, $available_hours, FALSE)))
{
$provider_id = $provider['id'];
$max_hours_count = count($available_hours);
Expand Down Expand Up @@ -448,7 +506,7 @@ public function ajax_register_appointment()
$captcha_phrase = $this->session->userdata('captcha_phrase');

// Validate the CAPTCHA string.
if ($require_captcha === '1' && $captcha_phrase !== $captcha)
if ($require_captcha === '1' && strtolower($captcha_phrase) !== strtolower($captcha))
{
$this->output
->set_content_type('application/json')
Expand All @@ -473,6 +531,16 @@ public function ajax_register_appointment()
$customer['language'] = config('language');
$customer_id = $this->customers_model->add($customer);

$appointment_start_instance = new DateTime($appointment['start_datetime']);
$appointment['end_datetime'] = $appointment_start_instance
->add(new DateInterval('PT' . $service['duration'] . 'M'))
->format('Y-m-d H:i:s');

if ( ! in_array($service['id'], $provider['services']))
{
throw new Exception('Invalid provider record selected for appointment.');
}

$appointment['id_users_customer'] = $customer_id;
$appointment['is_unavailable'] = (int)$appointment['is_unavailable']; // needs to be type casted
$appointment['id'] = $this->appointments_model->add($appointment);
Expand Down
22 changes: 19 additions & 3 deletions application/controllers/Backend_api.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public function __construct()
{
$this->privileges = $this->roles_model->get_privileges($this->session->userdata('role_slug'));
}
else
{
show_error('Forbidden', 403);
}
}

/**
Expand All @@ -66,6 +70,11 @@ public function ajax_get_calendar_events()
{
try
{
if ($this->privileges[PRIV_APPOINTMENTS]['view'] == FALSE)
{
throw new Exception('You do not have the required privileges for this task.');
}

$start_date = $this->input->post('startDate') . ' 00:00:00';
$end_date = $this->input->post('endDate') . ' 23:59:59';

Expand Down Expand Up @@ -1527,18 +1536,25 @@ public function ajax_get_google_calendars()
{
try
{
if ( ! $this->input->post('provider_id'))
$provider_id = $this->input->post('provider_id');

if ( ! $provider_id)
{
throw new Exception('Provider id is required in order to fetch the google calendars.');
}

if ($this->privileges[PRIV_USERS]['view'] == FALSE && $provider_id !== $this->session->userdata('user_id'))
{
throw new Exception('You do not have the required privileges for this task.');
}

// Check if selected provider has sync enabled.
$google_sync = $this->providers_model->get_setting('google_sync', $this->input->post('provider_id'));
$google_sync = $this->providers_model->get_setting('google_sync', $provider_id);

if ($google_sync)
{
$google_token = json_decode($this->providers_model->get_setting('google_token',
$this->input->post('provider_id')));
$provider_id));
$this->google_sync->refresh_token($google_token->refresh_token);

$calendars = $this->google_sync->get_google_calendars();
Expand Down
17 changes: 12 additions & 5 deletions application/controllers/Google.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public static function sync($provider_id = NULL)
$CI = get_instance();

// The user must be logged in.
if ($CI->session->userdata('user_id') == FALSE && is_cli() === FALSE)
if ( ! $CI->session->userdata('user_id') && ! is_cli())
{
return;
show_error('Forbidden', 403);
}

if ($provider_id === NULL)
Expand Down Expand Up @@ -204,7 +204,6 @@ public static function sync($provider_id = NULL)
continue;
}


// Record doesn't exist in the Easy!Appointments, so add the event now.
$appointment = [
'start_datetime' => $event_start->format('Y-m-d H:i:s'),
Expand Down Expand Up @@ -248,6 +247,11 @@ public static function sync($provider_id = NULL)
*/
public function oauth($provider_id)
{
if ( ! $this->session->userdata('user_id'))
{
show_error('Forbidden', 403);
}

// Store the provider id for use on the callback function.
$this->session->set_userdata('oauth_provider_id', $provider_id);

Expand All @@ -268,6 +272,11 @@ public function oauth($provider_id)
*/
public function oauth_callback()
{
if ( ! $this->session->userdata('user_id'))
{
show_error('Forbidden', 403);
}

$code = $this->input->get('code');

if (empty($code))
Expand Down Expand Up @@ -298,6 +307,4 @@ public function oauth_callback()
$this->output->set_output('Sync provider id not specified.');
}
}


}
3 changes: 3 additions & 0 deletions application/core/EA_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
* @property User_model $user_model
*
* @property Availability $availability
* @property Captcha_builder $captcha_builder
* @property Google_Sync $google_sync
* @property Ics_file $ics_file
* @property Notifications $notifications
Expand All @@ -66,6 +67,8 @@ public function __construct()
parent::__construct();

$this->configure_language();

rate_limit($this->input->ip_address());
}

/**
Expand Down
1 change: 1 addition & 0 deletions application/core/EA_Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
* @property User_model $user_model
*
* @property Availability $availability
* @property Captcha_builder $captcha_builder
* @property Google_Sync $google_sync
* @property Ics_file $ics_file
* @property Notifications $notifications
Expand Down
Loading

0 comments on commit 384d442

Please sign in to comment.