Skip to content

Commit

Permalink
Finalize the LDAP integration and complete SSO support in the login p…
Browse files Browse the repository at this point in the history
…age (#128)
  • Loading branch information
alextselegidis committed May 13, 2024
1 parent b0ffe4f commit 5967864
Show file tree
Hide file tree
Showing 67 changed files with 1,994 additions and 17 deletions.
10 changes: 10 additions & 0 deletions application/config/constants.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@

const DEFAULT_COMPANY_COLOR = '#ffffff';

const LDAP_DEFAULT_FILTER = '(&(objectClass=person)(|(cn={{KEYWORD}})(sn={{KEYWORD}})(mail={{KEYWORD}})(givenName={{KEYWORD}})(uid={{KEYWORD}})))';

const LDAP_DEFAULT_FIELD_MAPPING = [
'first_name' => 'givenname',
'last_name' => 'sn',
'email' => 'mail',
'phone_number' => 'telephonenumber',
'username' => 'cn',
];

/*
|--------------------------------------------------------------------------
| Webhook Actions
Expand Down
1 change: 1 addition & 0 deletions application/controllers/Admins.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Admins extends EA_Controller
'notes',
'timezone',
'language',
'ldap_dn',
'settings',
];

Expand Down
1 change: 1 addition & 0 deletions application/controllers/Customers.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Customers extends EA_Controller
'custom_field_3',
'custom_field_4',
'custom_field_5',
'ldap_dn',
];

/**
Expand Down
132 changes: 132 additions & 0 deletions application/controllers/Ldap_settings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php defined('BASEPATH') or exit('No direct script access allowed');

/* ----------------------------------------------------------------------------
* Easy!Appointments - Online Appointment Scheduler
*
* @package EasyAppointments
* @author A.Tselegidis <alextselegidis@gmail.com>
* @copyright Copyright (c) Alex Tselegidis
* @license https://opensource.org/licenses/GPL-3.0 - GPLv3
* @link https://easyappointments.org
* @since v1.5.0
* ---------------------------------------------------------------------------- */

/**
* LDAP settings controller.
*
* Handles LDAP settings related operations.
*
* @package Controllers
*/
class Ldap_settings extends EA_Controller
{
/**
* Ldap_settings constructor.
*/
public function __construct()
{
parent::__construct();

$this->load->model('settings_model');

$this->load->library('accounts');
$this->load->library('ldap_client');
}

/**
* Render the settings page.
*/
public function index(): void
{
session(['dest_url' => site_url('ldap_settings')]);

$user_id = session('user_id');

if (cannot('view', PRIV_SYSTEM_SETTINGS)) {
if ($user_id) {
abort(403, 'Forbidden');
}

redirect('login');

return;
}

$role_slug = session('role_slug');

script_vars([
'user_id' => $user_id,
'role_slug' => $role_slug,
'ldap_settings' => $this->settings_model->get('name like "ldap_%"'),
'ldap_default_filter' => LDAP_DEFAULT_FILTER,
'ldap_default_field_mapping' => LDAP_DEFAULT_FIELD_MAPPING,
]);

html_vars([
'page_title' => lang('ldap'),
'active_menu' => PRIV_SYSTEM_SETTINGS,
'user_display_name' => $this->accounts->get_user_display_name($user_id),
'roles' => $this->roles_model->get(),
]);

$this->load->view('pages/ldap_settings');
}

/**
* Save general settings.
*/
public function save(): void
{
try {
if (cannot('edit', PRIV_SYSTEM_SETTINGS)) {
throw new RuntimeException('You do not have the required permissions for this task.');
}

$settings = request('ldap_settings', []);

foreach ($settings as $setting) {
$existing_setting = $this->settings_model
->query()
->where('name', $setting['name'])
->get()
->row_array();

if (!empty($existing_setting)) {
$setting['id'] = $existing_setting['id'];
}

$this->settings_model->save($setting);
}

response();
} catch (Throwable $e) {
json_exception($e);
}
}

/**
* Search the LDAP directory.
*
* @return void
*/
public function search(): void
{
try {
if (cannot('edit', PRIV_SYSTEM_SETTINGS)) {
throw new RuntimeException('You do not have the required permissions for this task.');
}

if (!extension_loaded('ldap')) {
throw new RuntimeException('The LDAP extension is not loaded.');
}

$keyword = request('keyword');

$entries = $this->ldap_client->search($keyword);

json_response($entries);
} catch (Throwable $e) {
json_exception($e);
}
}
}
5 changes: 5 additions & 0 deletions application/controllers/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public function __construct()
parent::__construct();

$this->load->library('accounts');
$this->load->library('ldap_client');
$this->load->library('email_messages');

script_vars([
Expand Down Expand Up @@ -75,6 +76,10 @@ public function validate(): void

$user_data = $this->accounts->check_login($username, $password);

if (empty($user_data)) {
$user_data = $this->ldap_client->check_login($username, $password);
}

if (empty($user_data)) {
throw new InvalidArgumentException('Invalid credentials provided, please try again.');
}
Expand Down
12 changes: 12 additions & 0 deletions application/controllers/Providers.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class Providers extends EA_Controller
'timezone',
'language',
'is_private',
'ldap_dn',
'id_roles',
'settings',
'services',
Expand All @@ -52,6 +53,11 @@ class Providers extends EA_Controller
'services' => [],
];

public array $optional_provider_setting_fields = [
'working_plan' => null,
'working_plan_exceptions' => '{}',
];

/**
* Providers constructor.
*/
Expand All @@ -66,6 +72,8 @@ public function __construct()
$this->load->library('accounts');
$this->load->library('timezones');
$this->load->library('webhooks_client');

$this->optional_provider_setting_fields['working_plan'] = setting('company_working_plan');
}

/**
Expand Down Expand Up @@ -168,6 +176,8 @@ public function store(): void

$this->providers_model->optional($provider, $this->optional_provider_fields);

$this->providers_model->optional($provider['settings'], $this->optional_provider_setting_fields);

$provider_id = $this->providers_model->save($provider);

$provider = $this->providers_model->find($provider_id);
Expand Down Expand Up @@ -221,6 +231,8 @@ public function update(): void

$this->providers_model->optional($provider, $this->optional_provider_fields);

$this->providers_model->optional($provider['settings'], $this->optional_provider_setting_fields);

$provider_id = $this->providers_model->save($provider);

$provider = $this->providers_model->find($provider_id);
Expand Down
1 change: 1 addition & 0 deletions application/controllers/Secretaries.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Secretaries extends EA_Controller
'timezone',
'language',
'is_private',
'ldap_dn',
'id_roles',
'settings',
'providers',
Expand Down
1 change: 1 addition & 0 deletions application/core/EA_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
* @property Caldav_Sync $caldav_sync
* @property Ics_file $ics_file
* @property Instance $instance
* @property Ldap_client $ldap_client
* @property Notifications $notifications
* @property Permissions $permissions
* @property Synchronization $synchronization
Expand Down
16 changes: 16 additions & 0 deletions application/language/arabic/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End
16 changes: 16 additions & 0 deletions application/language/bulgarian/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End
16 changes: 16 additions & 0 deletions application/language/catalan/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End
16 changes: 16 additions & 0 deletions application/language/chinese/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End
16 changes: 16 additions & 0 deletions application/language/croatian/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End
16 changes: 16 additions & 0 deletions application/language/czech/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End
16 changes: 16 additions & 0 deletions application/language/danish/translations_lang.php
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,20 @@
$lang['caldav_server'] = 'CalDAV Server';
$lang['caldav_connection_info_prompt'] = 'Please enter the connection information of the target CalDAV server.';
$lang['connect'] = 'Connect';
$lang['ldap'] = 'LDAP';
$lang['ldap_info'] = 'This integration enables you to connect to an existing LDAP server and automatically import users into Easy!Appointments and let them SSO with their directory password (username must match).';
$lang['host'] = 'Host';
$lang['port'] = 'Port';
$lang['user_dn'] = 'User DN';
$lang['base_dn'] = 'Base DN';
$lang['keyword'] = 'Keyword';
$lang['ldap_search_hint'] = 'Provide a keyword to search through the LDAP directory for users that match the filter criteria.';
$lang['ldap_extension_not_loaded'] = 'The LDAP PHP extension is not loaded, but is required for this integration to work.';
$lang['field_mapping'] = 'Field Mapping';
$lang['content'] = 'Content';
$lang['active'] = 'Active';
$lang['user_imported'] = 'The user record was imported successfully.';
$lang['import'] = 'Import';
$lang['ldap_dn'] = 'LDAP DN';
$lang['role'] = 'Role';
// End

0 comments on commit 5967864

Please sign in to comment.