mirror of
https://github.com/alextselegidis/easyappointments.git
synced 2024-12-29 10:02:27 +03:00
Finalize the LDAP integration and complete SSO support in the login page (#128)
This commit is contained in:
parent
b0ffe4ff1f
commit
5967864e4a
67 changed files with 1994 additions and 17 deletions
|
@ -94,6 +94,16 @@ const EVENT_MINIMUM_DURATION = 5; // Minutes
|
|||
|
||||
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
|
||||
|
|
|
@ -34,6 +34,7 @@ class Admins extends EA_Controller
|
|||
'notes',
|
||||
'timezone',
|
||||
'language',
|
||||
'ldap_dn',
|
||||
'settings',
|
||||
];
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ class Customers extends EA_Controller
|
|||
'custom_field_3',
|
||||
'custom_field_4',
|
||||
'custom_field_5',
|
||||
'ldap_dn',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
132
application/controllers/Ldap_settings.php
Normal file
132
application/controllers/Ldap_settings.php
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ class Login extends EA_Controller
|
|||
parent::__construct();
|
||||
|
||||
$this->load->library('accounts');
|
||||
$this->load->library('ldap_client');
|
||||
$this->load->library('email_messages');
|
||||
|
||||
script_vars([
|
||||
|
@ -75,6 +76,10 @@ class Login extends EA_Controller
|
|||
|
||||
$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.');
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ class Providers extends EA_Controller
|
|||
'timezone',
|
||||
'language',
|
||||
'is_private',
|
||||
'ldap_dn',
|
||||
'id_roles',
|
||||
'settings',
|
||||
'services',
|
||||
|
@ -52,6 +53,11 @@ class Providers extends EA_Controller
|
|||
'services' => [],
|
||||
];
|
||||
|
||||
public array $optional_provider_setting_fields = [
|
||||
'working_plan' => null,
|
||||
'working_plan_exceptions' => '{}',
|
||||
];
|
||||
|
||||
/**
|
||||
* Providers constructor.
|
||||
*/
|
||||
|
@ -66,6 +72,8 @@ class Providers extends EA_Controller
|
|||
$this->load->library('accounts');
|
||||
$this->load->library('timezones');
|
||||
$this->load->library('webhooks_client');
|
||||
|
||||
$this->optional_provider_setting_fields['working_plan'] = setting('company_working_plan');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,6 +176,8 @@ class Providers extends EA_Controller
|
|||
|
||||
$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);
|
||||
|
@ -221,6 +231,8 @@ class Providers extends EA_Controller
|
|||
|
||||
$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);
|
||||
|
|
|
@ -36,6 +36,7 @@ class Secretaries extends EA_Controller
|
|||
'timezone',
|
||||
'language',
|
||||
'is_private',
|
||||
'ldap_dn',
|
||||
'id_roles',
|
||||
'settings',
|
||||
'providers',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['default_timezone'] = 'Default Timezone';
|
|||
$lang['default_timezone_hint'] = 'Set the default timezone value that will be used for new records.';
|
||||
$lang['default_language'] = 'Default Language';
|
||||
$lang['default_language_hint'] = 'Set the default language value that will be used for new records.';
|
||||
$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
|
||||
|
|
|
@ -461,4 +461,20 @@ $lang['sync_method_prompt'] = 'Which sync method would you like to use?';
|
|||
$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
|
||||
|
|
|
@ -161,4 +161,24 @@ class Accounts
|
|||
->get()
|
||||
->num_rows() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a user record based on the provided username value
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function get_user_by_username(string $username): ?array
|
||||
{
|
||||
$user_settings = $this->CI->db->get_where('user_settings', ['username' => $username])->row_array();
|
||||
|
||||
if (!$user_settings) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user_id = $user_settings['id_users'];
|
||||
|
||||
return $this->CI->users_model->find($user_id);
|
||||
}
|
||||
}
|
||||
|
|
236
application/libraries/Ldap_client.php
Normal file
236
application/libraries/Ldap_client.php
Normal file
|
@ -0,0 +1,236 @@
|
|||
<?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.4.0
|
||||
* ---------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Ldap_client library.
|
||||
*
|
||||
* Handles LDAP related functionality.
|
||||
*
|
||||
* @package Libraries
|
||||
*/
|
||||
class Ldap_client
|
||||
{
|
||||
/**
|
||||
* @var EA_Controller|CI_Controller
|
||||
*/
|
||||
protected EA_Controller|CI_Controller $CI;
|
||||
|
||||
/**
|
||||
* Ldap_client constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->CI = &get_instance();
|
||||
|
||||
$this->CI->load->model('roles_model');
|
||||
|
||||
$this->CI->load->library('timezones');
|
||||
$this->CI->load->library('accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the provided password with an LDAP hashed password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $hashed_password
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate_password(string $password, string $hashed_password): bool
|
||||
{
|
||||
if (empty($hashed_password) || ($hashed_password[0] !== '{' && $password === $hashed_password)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str_starts_with($hashed_password, '{MD5}')) {
|
||||
$encrypted_password = '{MD5}' . base64_encode(md5($password, true));
|
||||
} elseif (str_starts_with($hashed_password, '{SHA1}')) {
|
||||
$encrypted_password = '{SHA}' . base64_encode(sha1($password, true));
|
||||
} elseif (str_starts_with($hashed_password, '{SSHA}')) {
|
||||
$salt = substr(base64_decode(substr($hashed_password, 6)), 20);
|
||||
$encrypted_password = '{SSHA}' . base64_encode(sha1($password . $salt, true) . $salt);
|
||||
} else {
|
||||
throw new RuntimeException('Unsupported password hash format');
|
||||
}
|
||||
|
||||
return $hashed_password === $encrypted_password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try authenticating the user with LDAP
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @return array|null
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function check_login(string $username, string $password): ?array
|
||||
{
|
||||
if (empty($username)) {
|
||||
throw new InvalidArgumentException('No username value provided.');
|
||||
}
|
||||
|
||||
// Check LDAP environment and configuration
|
||||
|
||||
if (!extension_loaded('ldap')) {
|
||||
throw new RuntimeException('The LDAP extension is not loaded.');
|
||||
}
|
||||
|
||||
$ldap_is_active = setting('ldap_is_active');
|
||||
|
||||
if (!$ldap_is_active) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Match user by username
|
||||
|
||||
$user = $this->CI->accounts->get_user_by_username($username);
|
||||
|
||||
if (empty($user['ldap_dn'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Connect to LDAP server
|
||||
|
||||
$host = setting('ldap_host');
|
||||
$port = (int) setting('ldap_port');
|
||||
$user_dn = setting('ldap_user_dn');
|
||||
$ldap_password = setting('ldap_password');
|
||||
|
||||
$connection = ldap_connect($host, $port);
|
||||
|
||||
if (!$connection) {
|
||||
throw new Exception('Could not connect to LDAP server: ' . ldap_error($connection));
|
||||
}
|
||||
|
||||
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0); // We need this for doing an LDAP search.
|
||||
|
||||
$bind = ldap_bind($connection, $user_dn, $ldap_password);
|
||||
|
||||
if (!$bind) {
|
||||
throw new Exception('LDAP bind failed: ' . ldap_error($connection));
|
||||
}
|
||||
|
||||
// Check the provided password against the LDAP service
|
||||
|
||||
$filter = '(objectclass=*)';
|
||||
|
||||
$result = ldap_search($connection, $user['ldap_dn'], $filter);
|
||||
|
||||
if (!$result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ldap_entries = ldap_get_entries($connection, $result);
|
||||
|
||||
foreach ($ldap_entries as $ldap_entry) {
|
||||
if (!is_array($ldap_entry) || empty($ldap_entry['dn']) || $ldap_entry['dn'] !== $user['ldap_dn']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$this->validate_password($password, $ldap_entry['userpassword'][0])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$role = $this->CI->roles_model->find($user['id_roles']);
|
||||
|
||||
$default_timezone = $this->CI->timezones->get_default_timezone();
|
||||
|
||||
return [
|
||||
'user_id' => $user['id'],
|
||||
'user_email' => $user['email'],
|
||||
'username' => $username,
|
||||
'timezone' => !empty($user['timezone']) ? $user['timezone'] : $default_timezone,
|
||||
'language' => !empty($user['language']) ? $user['language'] : Config::LANGUAGE,
|
||||
'role_slug' => $role['slug'],
|
||||
];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the LDAP server based on the provided keyword and configuration.
|
||||
*
|
||||
* @param string $keyword
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function search(string $keyword): array
|
||||
{
|
||||
$host = setting('ldap_host');
|
||||
$port = (int) setting('ldap_port');
|
||||
$user_dn = setting('ldap_user_dn');
|
||||
$password = setting('ldap_password');
|
||||
$base_dn = setting('ldap_base_dn');
|
||||
$filter = setting('ldap_filter');
|
||||
|
||||
$connection = ldap_connect($host, $port);
|
||||
|
||||
if (!$connection) {
|
||||
throw new Exception('Could not connect to LDAP server: ' . ldap_error($connection));
|
||||
}
|
||||
|
||||
ldap_set_option($connection, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($connection, LDAP_OPT_REFERRALS, 0); // We need this for doing an LDAP search.
|
||||
|
||||
$bind = ldap_bind($connection, $user_dn, $password);
|
||||
|
||||
if (!$bind) {
|
||||
throw new Exception('LDAP bind failed: ' . ldap_error($connection));
|
||||
}
|
||||
|
||||
$wildcard_keyword = !empty($keyword) ? '*' . $keyword . '*' : '*';
|
||||
|
||||
$interpolated_filter = str_replace('{{KEYWORD}}', $wildcard_keyword, $filter);
|
||||
|
||||
$result = ldap_search($connection, $base_dn, $interpolated_filter);
|
||||
|
||||
if (!$result) {
|
||||
throw new Exception('Search failed: ' . ldap_error($connection));
|
||||
}
|
||||
|
||||
$ldap_entries = ldap_get_entries($connection, $result);
|
||||
|
||||
// Flatten the LDAP entries so that they become easier to import
|
||||
|
||||
$entries = [];
|
||||
|
||||
foreach ($ldap_entries as $ldap_entry) {
|
||||
if (!is_array($ldap_entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entry = [
|
||||
'dn' => $ldap_entry['dn'],
|
||||
];
|
||||
|
||||
foreach ($ldap_entry as $key => $value) {
|
||||
if (!is_array($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$entry[$key] = $value[0] ?? null;
|
||||
}
|
||||
|
||||
$entries[] = $entry;
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}
|
||||
}
|
102
application/migrations/057_add_ldap_rows_to_settings_table.php
Normal file
102
application/migrations/057_add_ldap_rows_to_settings_table.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?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.3.2
|
||||
* ---------------------------------------------------------------------------- */
|
||||
|
||||
class Migration_Add_ldap_rows_to_settings_table extends EA_Migration
|
||||
{
|
||||
/**
|
||||
* Upgrade method.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
$timestamps = [
|
||||
'create_datetime' => $now,
|
||||
'update_datetime' => $now,
|
||||
];
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_is_active'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_is_active', 'value' => '0']);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_host'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_host', 'value' => '']);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_port'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_port', 'value' => '']);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_user_dn'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_user_dn', 'value' => '']);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_password'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_password', 'value' => '']);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_base_dn'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_base_dn', 'value' => '']);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_filter'])->num_rows()) {
|
||||
$this->db->insert('settings', [...$timestamps, 'name' => 'ldap_filter', 'value' => LDAP_DEFAULT_FILTER]);
|
||||
}
|
||||
|
||||
if (!$this->db->get_where('settings', ['name' => 'ldap_field_mapping'])->num_rows()) {
|
||||
$this->db->insert('settings', [
|
||||
...$timestamps,
|
||||
'name' => 'ldap_field_mapping',
|
||||
'value' => json_encode(LDAP_DEFAULT_FIELD_MAPPING, JSON_PRETTY_PRINT),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downgrade method.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_is_active'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_is_active']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_host'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_host']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_port'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_port']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_user_dn'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_user_dn']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_password'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_password']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_base_dn'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_base_dn']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_filter'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_filter']);
|
||||
}
|
||||
|
||||
if ($this->db->get_where('settings', ['name' => 'ldap_field_mapping'])->num_rows()) {
|
||||
$this->db->delete('settings', ['name' => 'ldap_field_mapping']);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?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.4.0
|
||||
* ---------------------------------------------------------------------------- */
|
||||
|
||||
class Migration_Add_ldap_dn_column_to_users_table extends EA_Migration
|
||||
{
|
||||
/**
|
||||
* Upgrade method.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
if (!$this->db->field_exists('ldap_dn', 'users')) {
|
||||
$fields = [
|
||||
'ldap_dn' => [
|
||||
'type' => 'TEXT',
|
||||
'null' => true,
|
||||
'after' => 'is_private',
|
||||
],
|
||||
];
|
||||
|
||||
$this->dbforge->add_column('users', $fields);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downgrade method.
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
if ($this->db->field_exists('ldap_dn', 'users')) {
|
||||
$this->dbforge->drop_column('users', 'ldap_dn');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@ class Admins_model extends EA_Model
|
|||
'timezone' => 'timezone',
|
||||
'language' => 'language',
|
||||
'notes' => 'notes',
|
||||
'ldapDn' => 'ldap_dn',
|
||||
'roleId' => 'id_roles',
|
||||
];
|
||||
|
||||
|
@ -556,6 +557,8 @@ class Admins_model extends EA_Model
|
|||
'zip' => $admin['zip_code'],
|
||||
'notes' => $admin['notes'],
|
||||
'timezone' => $admin['timezone'],
|
||||
'language' => $admin['language'],
|
||||
'ldapDn' => $admin['ldap_dn'],
|
||||
'settings' => [
|
||||
'username' => $admin['settings']['username'],
|
||||
'notifications' => filter_var($admin['settings']['notifications'], FILTER_VALIDATE_BOOLEAN),
|
||||
|
@ -624,6 +627,14 @@ class Admins_model extends EA_Model
|
|||
$decoded_resource['timezone'] = $admin['timezone'];
|
||||
}
|
||||
|
||||
if (array_key_exists('language', $admin)) {
|
||||
$decoded_resource['language'] = $admin['language'];
|
||||
}
|
||||
|
||||
if (array_key_exists('ldapDn', $admin)) {
|
||||
$decoded_resource['ldap_dn'] = $admin['ldapDn'];
|
||||
}
|
||||
|
||||
if (array_key_exists('settings', $admin)) {
|
||||
if (empty($decoded_resource['settings'])) {
|
||||
$decoded_resource['settings'] = [];
|
||||
|
|
|
@ -49,6 +49,7 @@ class Customers_model extends EA_Model
|
|||
'customField4' => 'custom_field_4',
|
||||
'customField5' => 'custom_field_5',
|
||||
'notes' => 'notes',
|
||||
'ldapDn' => 'ldap_dn',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -461,6 +462,7 @@ class Customers_model extends EA_Model
|
|||
'customField3' => $customer['custom_field_3'],
|
||||
'customField4' => $customer['custom_field_4'],
|
||||
'customField5' => $customer['custom_field_5'],
|
||||
'ldapDn' => $customer['ldap_dn'],
|
||||
];
|
||||
|
||||
$customer = $encoded_resource;
|
||||
|
@ -532,6 +534,10 @@ class Customers_model extends EA_Model
|
|||
$decoded_resource['custom_field_5'] = $customer['customField5'];
|
||||
}
|
||||
|
||||
if (array_key_exists('ldapDn', $customer)) {
|
||||
$decoded_resource['ldap_dn'] = $customer['ldapDn'];
|
||||
}
|
||||
|
||||
if (array_key_exists('notes', $customer)) {
|
||||
$decoded_resource['notes'] = $customer['notes'];
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ class Providers_model extends EA_Model
|
|||
'language' => 'language',
|
||||
'notes' => 'notes',
|
||||
'isPrivate' => 'is_private',
|
||||
'ldapDn' => 'ldap_dn',
|
||||
'roleId' => 'id_roles',
|
||||
];
|
||||
|
||||
|
@ -749,6 +750,7 @@ class Providers_model extends EA_Model
|
|||
'zip' => $provider['zip_code'],
|
||||
'notes' => $provider['notes'],
|
||||
'is_private' => $provider['is_private'],
|
||||
'ldapDn' => $provider['ldap_dn'],
|
||||
'timezone' => $provider['timezone'],
|
||||
];
|
||||
|
||||
|
@ -869,6 +871,10 @@ class Providers_model extends EA_Model
|
|||
$decoded_resource['is_private'] = (bool) $provider['isPrivate'];
|
||||
}
|
||||
|
||||
if (array_key_exists('ldapDn', $provider)) {
|
||||
$decoded_resource['ldap_dn'] = $provider['ldapDn'];
|
||||
}
|
||||
|
||||
if (array_key_exists('settings', $provider)) {
|
||||
if (empty($decoded_resource['settings'])) {
|
||||
$decoded_resource['settings'] = [];
|
||||
|
|
|
@ -45,6 +45,7 @@ class Secretaries_model extends EA_Model
|
|||
'timezone' => 'timezone',
|
||||
'language' => 'language',
|
||||
'notes' => 'notes',
|
||||
'ldapDn' => 'ldap_dn',
|
||||
'roleId' => 'id_roles',
|
||||
];
|
||||
|
||||
|
@ -601,6 +602,8 @@ class Secretaries_model extends EA_Model
|
|||
'notes' => $secretary['notes'],
|
||||
'providers' => $secretary['providers'],
|
||||
'timezone' => $secretary['timezone'],
|
||||
'language' => $secretary['language'],
|
||||
'ldapDn' => $secretary['ldap_dn'],
|
||||
'settings' => [
|
||||
'username' => $secretary['settings']['username'],
|
||||
'notifications' => filter_var($secretary['settings']['notifications'], FILTER_VALIDATE_BOOLEAN),
|
||||
|
@ -669,6 +672,14 @@ class Secretaries_model extends EA_Model
|
|||
$decoded_resource['timezone'] = $secretary['timezone'];
|
||||
}
|
||||
|
||||
if (array_key_exists('language', $secretary)) {
|
||||
$decoded_resource['language'] = $secretary['language'];
|
||||
}
|
||||
|
||||
if (array_key_exists('ldapDn', $secretary)) {
|
||||
$decoded_resource['ldap_dn'] = $secretary['ldapDn'];
|
||||
}
|
||||
|
||||
if (array_key_exists('providers', $secretary)) {
|
||||
$decoded_resource['providers'] = $secretary['providers'];
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ class Users_model extends EA_Model
|
|||
'zip' => 'zip_code',
|
||||
'timezone' => 'timezone',
|
||||
'language' => 'language',
|
||||
'ldapDn' => 'ldap_dn',
|
||||
'notes' => 'notes',
|
||||
'roleId' => 'id_roles',
|
||||
];
|
||||
|
@ -125,7 +126,7 @@ class Users_model extends EA_Model
|
|||
$settings['salt'] = generate_salt();
|
||||
$settings['password'] = hash_password($settings['salt'], $settings['password']);
|
||||
|
||||
$this->save_settings($user['id'], $settings);
|
||||
$this->set_settings($user['id'], $settings);
|
||||
|
||||
return $user['id'];
|
||||
}
|
||||
|
@ -138,7 +139,7 @@ class Users_model extends EA_Model
|
|||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
protected function save_settings(int $user_id, array $settings): void
|
||||
protected function set_settings(int $user_id, array $settings): void
|
||||
{
|
||||
if (empty($settings)) {
|
||||
throw new InvalidArgumentException('The settings argument cannot be empty.');
|
||||
|
@ -156,6 +157,22 @@ class Users_model extends EA_Model
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user settings.
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function get_settings(int $user_id): array
|
||||
{
|
||||
$settings = $this->db->get_where('user_settings', ['id_users' => $user_id])->row_array();
|
||||
|
||||
unset($settings['id_users'], $settings['password'], $settings['salt']);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a user setting.
|
||||
*
|
||||
|
@ -200,7 +217,7 @@ class Users_model extends EA_Model
|
|||
throw new RuntimeException('Could not update user.');
|
||||
}
|
||||
|
||||
$this->save_settings($user['id'], $settings);
|
||||
$this->set_settings($user['id'], $settings);
|
||||
|
||||
return $user['id'];
|
||||
}
|
||||
|
@ -236,9 +253,7 @@ class Users_model extends EA_Model
|
|||
|
||||
$this->cast($user);
|
||||
|
||||
$user['settings'] = $this->db->get_where('user_settings', ['id_users' => $user_id])->row_array();
|
||||
|
||||
unset($user['settings']['id_users'], $user['settings']['password'], $user['settings']['salt']);
|
||||
$user['settings'] = $this->get_settings($user['id']);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
@ -346,10 +361,7 @@ class Users_model extends EA_Model
|
|||
|
||||
foreach ($users as &$user) {
|
||||
$this->cast($user);
|
||||
|
||||
$user['settings'] = $this->db->get_where('user_settings', ['id_users' => $user['id']])->row_array();
|
||||
|
||||
unset($user['settings']['id_users'], $user['settings']['password'], $user['settings']['salt']);
|
||||
$user['settings'] = $this->get_settings($user['id']);
|
||||
}
|
||||
|
||||
return $users;
|
||||
|
@ -383,10 +395,7 @@ class Users_model extends EA_Model
|
|||
|
||||
foreach ($users as &$user) {
|
||||
$this->cast($user);
|
||||
|
||||
$user['settings'] = $this->db->get_where('user_settings', ['id_users' => $user['id']])->row_array();
|
||||
|
||||
unset($user['settings']['id_users'], $user['settings']['password'], $user['settings']['salt']);
|
||||
$user['settings'] = $this->get_settings($user['id']);
|
||||
}
|
||||
|
||||
return $users;
|
||||
|
|
105
application/views/components/ldap_import_modal.php
Normal file
105
application/views/components/ldap_import_modal.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
/**
|
||||
* Local variables.
|
||||
*
|
||||
* @var array $roles
|
||||
*/
|
||||
?>
|
||||
|
||||
<div id="ldap-import-modal" class="modal fade">
|
||||
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title"><?= lang('import') ?></h3>
|
||||
<button class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-ldap-dn">
|
||||
<?= lang('ldap_dn') ?>
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<input id="ldap-import-ldap-dn" class="form-control required" maxlength="256">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-role-slug">
|
||||
<?= lang('role') ?>
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<select id="ldap-import-role-slug" class="form-control required">
|
||||
<?php foreach ($roles as $role): ?>
|
||||
<option value="<?= $role['slug'] ?>">
|
||||
<?= $role['name'] ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-first-name">
|
||||
<?= lang('first_name') ?>
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<input id="ldap-import-first-name" class="form-control required" maxlength="256">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-last-name">
|
||||
<?= lang('last_name') ?>
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<input id="ldap-import-last-name" class="form-control required" maxlength="256">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-email">
|
||||
<?= lang('email') ?>
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<input id="ldap-import-email" class="form-control required" max="512">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-phone-number">
|
||||
<?= lang('phone_number') ?>
|
||||
<span class="text-danger">*</span>
|
||||
</label>
|
||||
<input id="ldap-import-phone-number" class="form-control required" max="128">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-username">
|
||||
<?= lang('username') ?>
|
||||
</label>
|
||||
<input id="ldap-import-username" class="form-control" maxlength="256">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-import-password">
|
||||
<?= lang('password') ?>
|
||||
</label>
|
||||
<input type="password" id="ldap-import-password" class="form-control"
|
||||
maxlength="512" autocomplete="new-password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
<?= lang('cancel') ?>
|
||||
</button>
|
||||
<button id="ldap-import-save" class="btn btn-primary">
|
||||
<i class="fas fa-check-square me-2"></i>
|
||||
<?= lang('save') ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php section('scripts'); ?>
|
||||
|
||||
<script src="<?= asset_url('assets/js/components/ldap_import_modal.js') ?>"></script>
|
||||
|
||||
<?php end_section('scripts'); ?>
|
|
@ -208,6 +208,15 @@
|
|||
]); ?>
|
||||
</div>
|
||||
|
||||
<?php if (setting('ldap_is_active')): ?>
|
||||
<div class="mb-3">
|
||||
<label for="ldap-dn" class="form-label">
|
||||
<?= lang('ldap_dn') ?>
|
||||
</label>
|
||||
<input type="text" id="ldap-dn" class="form-control" maxlength="100" disabled/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div>
|
||||
<label class="form-label mb-3">
|
||||
<?= lang('options') ?>
|
||||
|
|
|
@ -185,6 +185,15 @@
|
|||
]); ?>
|
||||
</div>
|
||||
|
||||
<?php if (setting('ldap_is_active')): ?>
|
||||
<div class="mb-3">
|
||||
<label for="ldap-dn" class="form-label">
|
||||
<?= lang('ldap_dn') ?>
|
||||
</label>
|
||||
<input type="text" id="ldap-dn" class="form-control" maxlength="100" disabled/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php component('custom_fields', [
|
||||
'disabled' => true,
|
||||
]); ?>
|
||||
|
|
|
@ -111,6 +111,29 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 mb-4">
|
||||
<div class="card h-100">
|
||||
<div class="card-header">
|
||||
<h5 class="fw-light text-black-50 mb-0">
|
||||
<?= lang('ldap') ?>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3 integration-info">
|
||||
<small>
|
||||
<?= lang('ldap_info') ?>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-white border-0">
|
||||
<a href="<?= site_url('ldap_settings') ?>" class="btn btn-outline-primary w-100">
|
||||
<i class="fas fa-cogs me-2"></i>
|
||||
<?= lang('configure') ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php slot('after_integration_cards'); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
|
165
application/views/pages/ldap_settings.php
Normal file
165
application/views/pages/ldap_settings.php
Normal file
|
@ -0,0 +1,165 @@
|
|||
<?php extend('layouts/backend_layout'); ?>
|
||||
|
||||
<?php section('content'); ?>
|
||||
|
||||
<div id="ldap-settings-page" class="container backend-page">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 offset-sm-1">
|
||||
<?php component('settings_nav'); ?>
|
||||
</div>
|
||||
<div id="ldap-settings" class="col-sm-6">
|
||||
<form>
|
||||
<fieldset>
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom mb-4 py-2">
|
||||
<h4 class="text-black-50 mb-0 fw-light">
|
||||
<?= lang('ldap') ?>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
<a href="<?= site_url('integrations') ?>" class="btn btn-outline-primary me-2">
|
||||
<i class="fas fa-chevron-left me-2"></i>
|
||||
<?= lang('back') ?>
|
||||
</a>
|
||||
|
||||
<?php if (can('edit', PRIV_SYSTEM_SETTINGS)): ?>
|
||||
<button type="button" id="save-settings" class="btn btn-primary">
|
||||
<i class="fas fa-check-square me-2"></i>
|
||||
<?= lang('save') ?>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (!extension_loaded('ldap')): ?>
|
||||
<div class="alert alert-warning">
|
||||
<?= lang('ldap_extension_not_loaded') ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="mb-3">
|
||||
<div class="form-check form-switch mb-3">
|
||||
<input class="form-check-input" type="checkbox" id="ldap-is-active" data-field="ldap_is_active">
|
||||
<label class="form-check-label" for="ldap-is-active">
|
||||
<?= lang('active') ?>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-host">
|
||||
<?= lang('host') ?>
|
||||
</label>
|
||||
<input id="ldap-host" class="form-control" data-field="ldap_host">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-port">
|
||||
<?= lang('port') ?>
|
||||
</label>
|
||||
<input id="ldap-port" class="form-control" data-field="ldap_port">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-user_dn">
|
||||
<?= lang('user_dn') ?>
|
||||
</label>
|
||||
<input id="ldap-user_dn" class="form-control" data-field="ldap_user_dn">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-password">
|
||||
<?= lang('password') ?>
|
||||
</label>
|
||||
<input id="ldap-password" type="password" class="form-control" data-field="ldap_password">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="ldap-base-dn">
|
||||
<?= lang('base_dn') ?>
|
||||
</label>
|
||||
<input id="ldap-base-dn" class="form-control" data-field="ldap_base_dn">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="d-flex mb-2">
|
||||
<label class="form-label mb-0" for="ldap-filter">
|
||||
<?= lang('filter') ?>
|
||||
</label>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary py-0 ms-auto" id="ldap-reset-filter">
|
||||
<i class="fas fa-undo me-2"></i>
|
||||
<?= lang('reset') ?>
|
||||
</button>
|
||||
</div>
|
||||
<input id="ldap-filter" class="form-control" data-field="ldap_filter">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<div class="d-flex mb-2">
|
||||
<label class="form-label mb-0" for="ldap-field-mapping">
|
||||
<?= lang('field_mapping') ?>
|
||||
</label>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary py-0 ms-auto" id="ldap-reset-field-mapping">
|
||||
<i class="fas fa-undo me-2"></i>
|
||||
<?= lang('reset') ?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<textarea id="ldap-field-mapping" class="form-control" rows="5" data-field="ldap_field_mapping"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php slot('after_primary_appointment_fields'); ?>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom mb-4 py-2">
|
||||
<h4 class="text-black-50 mb-0 fw-light">
|
||||
<?= lang('search') ?>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<p class="text-muted small">
|
||||
<?= lang('ldap_search_hint') ?>
|
||||
</p>
|
||||
|
||||
<form id="ldap-search-form" class="mb-3">
|
||||
<label class="form-label" for="ldap-search-keyword">
|
||||
<?= lang('keyword') ?>
|
||||
</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="ldap-search-keyword" class="form-control">
|
||||
|
||||
<button type="submit" class="btn btn-outline-primary">
|
||||
<?= lang('search') ?>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="ldap-search-results" class="mb-3">
|
||||
<!-- JS -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php component('ldap_import_modal', [
|
||||
'roles' => vars('roles'),
|
||||
]); ?>
|
||||
|
||||
<?php end_section('content'); ?>
|
||||
|
||||
<?php section('scripts'); ?>
|
||||
|
||||
<script src="<?= asset_url('assets/js/utils/url.js') ?>"></script>
|
||||
<script src="<?= asset_url('assets/js/http/customers_http_client.js') ?>"></script>
|
||||
<script src="<?= asset_url('assets/js/http/providers_http_client.js') ?>"></script>
|
||||
<script src="<?= asset_url('assets/js/http/secretaries_http_client.js') ?>"></script>
|
||||
<script src="<?= asset_url('assets/js/http/admins_http_client.js') ?>"></script>
|
||||
<script src="<?= asset_url('assets/js/http/ldap_settings_http_client.js') ?>"></script>
|
||||
<script src="<?= asset_url('assets/js/pages/ldap_settings.js') ?>"></script>
|
||||
|
||||
<?php end_section('scripts'); ?>
|
|
@ -230,6 +230,15 @@
|
|||
]); ?>
|
||||
</div>
|
||||
|
||||
<?php if (setting('ldap_is_active')): ?>
|
||||
<div class="mb-3">
|
||||
<label for="ldap-dn" class="form-label">
|
||||
<?= lang('ldap_dn') ?>
|
||||
</label>
|
||||
<input type="text" id="ldap-dn" class="form-control" maxlength="100" disabled/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div>
|
||||
<label class="form-label mb-3">
|
||||
<?= lang('options') ?>
|
||||
|
|
|
@ -207,6 +207,15 @@
|
|||
]); ?>
|
||||
</div>
|
||||
|
||||
<?php if (setting('ldap_is_active')): ?>
|
||||
<div class="mb-3">
|
||||
<label for="ldap-dn" class="form-label">
|
||||
<?= lang('ldap_dn') ?>
|
||||
</label>
|
||||
<input type="text" id="ldap-dn" class="form-control" maxlength="100" disabled/>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div>
|
||||
<label class="form-label mb-3">
|
||||
<?= lang('options') ?>
|
||||
|
|
170
assets/js/components/ldap_import_modal.js
Normal file
170
assets/js/components/ldap_import_modal.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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 import modal component.
|
||||
*
|
||||
* This module implements the LDAP import modal functionality.
|
||||
*
|
||||
* This module requires the following scripts:
|
||||
*
|
||||
* - App.Http.Customers
|
||||
* - App.Http.Providers
|
||||
* - App.Http.Secretaries
|
||||
* - App.Http.Admins
|
||||
*/
|
||||
App.Components.LdapImportModal = (function () {
|
||||
const $modal = $('#ldap-import-modal');
|
||||
const $save = $('#ldap-import-save');
|
||||
const $firstName = $('#ldap-import-first-name');
|
||||
const $lastName = $('#ldap-import-last-name');
|
||||
const $email = $('#ldap-import-email');
|
||||
const $phoneNumber = $('#ldap-import-phone-number');
|
||||
const $username = $('#ldap-import-username');
|
||||
const $ldapDn = $('#ldap-import-ldap-dn');
|
||||
const $roleSlug = $('#ldap-import-role-slug');
|
||||
const $password = $('#ldap-import-password');
|
||||
|
||||
let deferred;
|
||||
|
||||
function validate() {
|
||||
$modal.find('.is-invalid').removeClass('is-invalid');
|
||||
|
||||
// Check required fields.
|
||||
let missingRequiredField = false;
|
||||
|
||||
$modal.find('.required').each((index, requiredField) => {
|
||||
if ($(requiredField).val() === '' || $(requiredField).val() === null) {
|
||||
$(requiredField).addClass('is-invalid');
|
||||
missingRequiredField = true;
|
||||
}
|
||||
});
|
||||
|
||||
return !missingRequiredField;
|
||||
}
|
||||
|
||||
function getHttpClient(roleSlug) {
|
||||
switch (roleSlug) {
|
||||
case App.Layouts.Backend.DB_SLUG_CUSTOMER:
|
||||
return App.Http.Customers;
|
||||
case App.Layouts.Backend.DB_SLUG_PROVIDER:
|
||||
return App.Http.Providers;
|
||||
case App.Layouts.Backend.DB_SLUG_SECRETARY:
|
||||
return App.Http.Secretaries;
|
||||
case App.Layouts.Backend.DB_SLUG_ADMIN:
|
||||
return App.Http.Admins;
|
||||
default:
|
||||
throw new Error(`Unsupported role slug provided: ${roleSlug}`);
|
||||
}
|
||||
}
|
||||
|
||||
function getUser(roleSlug) {
|
||||
const user = {
|
||||
first_name: $firstName.val(),
|
||||
last_name: $lastName.val(),
|
||||
email: $email.val(),
|
||||
phone_number: $phoneNumber.val(),
|
||||
ldap_dn: $ldapDn.val(),
|
||||
};
|
||||
|
||||
if (roleSlug !== App.Layouts.Backend.DB_SLUG_CUSTOMER) {
|
||||
user.settings = {
|
||||
username: $username.val(),
|
||||
password: $password.val(),
|
||||
notification: 1,
|
||||
};
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through the available values and try to load as many as possible based on the provided mapping.
|
||||
*
|
||||
* @param {Object} entry
|
||||
* @param {Object} ldapFieldMapping
|
||||
*/
|
||||
function loadEntry(entry, ldapFieldMapping) {
|
||||
$ldapDn.val(entry.dn);
|
||||
$firstName.val(entry?.[ldapFieldMapping?.first_name] ?? '');
|
||||
$lastName.val(entry?.[ldapFieldMapping?.last_name] ?? '');
|
||||
$email.val(entry?.[ldapFieldMapping?.email] ?? '');
|
||||
$phoneNumber.val(entry?.[ldapFieldMapping?.phone_number] ?? '');
|
||||
$username.val(entry?.[ldapFieldMapping?.username] ?? '');
|
||||
$password.val('');
|
||||
}
|
||||
|
||||
function onSaveClick() {
|
||||
if (!validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const roleSlug = $roleSlug.val();
|
||||
|
||||
const user = getUser(roleSlug);
|
||||
|
||||
const httpClient = getHttpClient(roleSlug);
|
||||
|
||||
httpClient.store(user).done(() => {
|
||||
deferred.resolve();
|
||||
deferred = undefined;
|
||||
$modal.modal('hide');
|
||||
});
|
||||
}
|
||||
|
||||
function onModalHidden() {
|
||||
resetModal();
|
||||
|
||||
if (deferred) {
|
||||
deferred.reject();
|
||||
}
|
||||
}
|
||||
|
||||
function resetModal() {
|
||||
$modal.find('input, select, textarea').val('');
|
||||
$modal.find(':checkbox').prop('checked', false);
|
||||
$roleSlug.val(App.Layouts.Backend.DB_SLUG_PROVIDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the import modal for an LDAP entry.
|
||||
*
|
||||
* @param {Object} entry
|
||||
* @param {Object} ldapFieldMapping
|
||||
*
|
||||
* @return {Object} $.Deferred
|
||||
*/
|
||||
function open(entry, ldapFieldMapping) {
|
||||
resetModal();
|
||||
|
||||
deferred = $.Deferred();
|
||||
|
||||
loadEntry(entry, ldapFieldMapping);
|
||||
|
||||
$modal.modal('show');
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the module.
|
||||
*/
|
||||
function initialize() {
|
||||
$save.on('click', onSaveClick);
|
||||
$modal.on('hidden.bs.modal', onModalHidden);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', initialize);
|
||||
|
||||
return {
|
||||
open,
|
||||
};
|
||||
})();
|
58
assets/js/http/ldap_settings_http_client.js
Normal file
58
assets/js/http/ldap_settings_http_client.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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 HTTP client.
|
||||
*
|
||||
* This module implements the LDAP settings related HTTP requests.
|
||||
*/
|
||||
App.Http.LdapSettings = (function () {
|
||||
/**
|
||||
* Save LDAP settings.
|
||||
*
|
||||
* @param {Object} ldapSettings
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function save(ldapSettings) {
|
||||
const url = App.Utils.Url.siteUrl('ldap_settings/save');
|
||||
|
||||
const data = {
|
||||
csrf_token: vars('csrf_token'),
|
||||
ldap_settings: ldapSettings,
|
||||
};
|
||||
|
||||
return $.post(url, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search LDAP server.
|
||||
*
|
||||
* @param {String} keyword
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
function search(keyword) {
|
||||
const url = App.Utils.Url.siteUrl('ldap_settings/search');
|
||||
|
||||
const data = {
|
||||
csrf_token: vars('csrf_token'),
|
||||
keyword,
|
||||
};
|
||||
|
||||
return $.post(url, data);
|
||||
}
|
||||
|
||||
return {
|
||||
save,
|
||||
search,
|
||||
};
|
||||
})();
|
|
@ -29,6 +29,7 @@ App.Pages.Admins = (function () {
|
|||
const $notes = $('#notes');
|
||||
const $language = $('#language');
|
||||
const $timezone = $('#timezone');
|
||||
const $ldapDn = $('#ldap-dn');
|
||||
const $username = $('#username');
|
||||
const $password = $('#password');
|
||||
const $passwordConfirmation = $('#password-confirm');
|
||||
|
@ -186,6 +187,7 @@ App.Pages.Admins = (function () {
|
|||
notes: $notes.val(),
|
||||
language: $language.val(),
|
||||
timezone: $timezone.val(),
|
||||
ldap_dn: $ldapDn.val(),
|
||||
settings: {
|
||||
username: $username.val(),
|
||||
notifications: Number($notifications.prop('checked')),
|
||||
|
@ -364,6 +366,7 @@ App.Pages.Admins = (function () {
|
|||
$notes.val(admin.notes);
|
||||
$language.val(admin.language);
|
||||
$timezone.val(admin.timezone);
|
||||
$ldapDn.val(admin.ldap_dn);
|
||||
|
||||
$username.val(admin.settings.username);
|
||||
$calendarView.val(admin.settings.calendar_view);
|
||||
|
|
|
@ -27,6 +27,7 @@ App.Pages.Customers = (function () {
|
|||
const $zipCode = $('#zip-code');
|
||||
const $timezone = $('#timezone');
|
||||
const $language = $('#language');
|
||||
const $ldapDn = $('#ldap-dn');
|
||||
const $customField1 = $('#custom-field-1');
|
||||
const $customField2 = $('#custom-field-2');
|
||||
const $customField3 = $('#custom-field-3');
|
||||
|
@ -138,6 +139,7 @@ App.Pages.Customers = (function () {
|
|||
custom_field_3: $customField3.val(),
|
||||
custom_field_4: $customField4.val(),
|
||||
custom_field_5: $customField5.val(),
|
||||
ldap_dn: $ldapDn.val(),
|
||||
};
|
||||
|
||||
if ($id.val()) {
|
||||
|
@ -288,6 +290,7 @@ App.Pages.Customers = (function () {
|
|||
$notes.val(customer.notes);
|
||||
$timezone.val(customer.timezone);
|
||||
$language.val(customer.language || 'english');
|
||||
$ldapDn.val(customer.ldap_dn);
|
||||
$customField1.val(customer.custom_field_1);
|
||||
$customField2.val(customer.custom_field_2);
|
||||
$customField3.val(customer.custom_field_3);
|
||||
|
|
246
assets/js/pages/ldap_settings.js
Normal file
246
assets/js/pages/ldap_settings.js
Normal file
|
@ -0,0 +1,246 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* 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 page.
|
||||
*
|
||||
* This module implements the functionality of the LDAP settings page.
|
||||
*/
|
||||
App.Pages.LdapSettings = (function () {
|
||||
const $saveSettings = $('#save-settings');
|
||||
const $searchForm = $('#ldap-search-form');
|
||||
const $searchKeyword = $('#ldap-search-keyword');
|
||||
const $searchResults = $('#ldap-search-results');
|
||||
const $ldapFilter = $('#ldap-filter');
|
||||
const $ldapFieldMapping = $('#ldap-field-mapping');
|
||||
const $resetFilter = $('#ldap-reset-filter');
|
||||
const $resetFieldMapping = $('#ldap-reset-field-mapping');
|
||||
|
||||
/**
|
||||
* Check if the form has invalid values.
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
function isInvalid() {
|
||||
try {
|
||||
$('#ldap-settings .is-invalid').removeClass('is-invalid');
|
||||
|
||||
// Validate required fields.
|
||||
|
||||
let missingRequiredFields = false;
|
||||
|
||||
$('#ldap-settings .required').each((index, requiredField) => {
|
||||
const $requiredField = $(requiredField);
|
||||
|
||||
if (!$requiredField.val()) {
|
||||
$requiredField.addClass('is-invalid');
|
||||
missingRequiredFields = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (missingRequiredFields) {
|
||||
throw new Error(lang('fields_are_required'));
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
App.Layouts.Backend.displayNotification(error.message);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function deserialize(ldapSettings) {
|
||||
ldapSettings.forEach((ldapSetting) => {
|
||||
const $field = $('[data-field="' + ldapSetting.name + '"]');
|
||||
|
||||
$field.is(':checkbox')
|
||||
? $field.prop('checked', Boolean(Number(ldapSetting.value)))
|
||||
: $field.val(ldapSetting.value);
|
||||
});
|
||||
}
|
||||
|
||||
function serialize() {
|
||||
const ldapSettings = [];
|
||||
|
||||
$('[data-field]').each((index, field) => {
|
||||
const $field = $(field);
|
||||
|
||||
ldapSettings.push({
|
||||
name: $field.data('field'),
|
||||
value: $field.is(':checkbox') ? Number($field.prop('checked')) : $field.val(),
|
||||
});
|
||||
});
|
||||
|
||||
return ldapSettings;
|
||||
}
|
||||
|
||||
function getLdapFieldMapping() {
|
||||
const jsonLdapFieldMapping = $ldapFieldMapping.val();
|
||||
return JSON.parse(jsonLdapFieldMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current server settings.
|
||||
*/
|
||||
function saveSettings() {
|
||||
if (isInvalid()) {
|
||||
App.Layouts.Backend.displayNotification(lang('settings_are_invalid'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const ldapSettings = serialize();
|
||||
|
||||
return App.Http.LdapSettings.save(ldapSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the LDAP server based on a keyword.
|
||||
*/
|
||||
function searchServer() {
|
||||
$searchResults.empty();
|
||||
|
||||
const keyword = $searchKeyword.val();
|
||||
|
||||
if (!keyword) {
|
||||
return;
|
||||
}
|
||||
|
||||
App.Http.LdapSettings.search(keyword).done((entries) => {
|
||||
$searchResults.empty();
|
||||
|
||||
if (!entries?.length) {
|
||||
renderNoRecordsFound().appendTo($searchResults);
|
||||
return;
|
||||
}
|
||||
|
||||
entries.forEach((entry) => {
|
||||
renderEntry(entry).appendTo($searchResults);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the account information.
|
||||
*/
|
||||
function onSaveSettingsClick() {
|
||||
saveSettings().done(() => {
|
||||
App.Layouts.Backend.displayNotification(lang('settings_saved'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the field value back to the original state.
|
||||
*/
|
||||
function onResetFilterClick() {
|
||||
$ldapFilter.val(vars('ldap_default_filter'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the field value back to the original state.
|
||||
*/
|
||||
function onResetFieldMappingClick() {
|
||||
const defaultFieldMapping = vars('ldap_default_field_mapping');
|
||||
const jsonDefaultFieldMapping = JSON.stringify(defaultFieldMapping, null, 2);
|
||||
$ldapFieldMapping.val(jsonDefaultFieldMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the LDAP import button click
|
||||
*/
|
||||
function onLdapImportClick(event) {
|
||||
const $target = $(event.target);
|
||||
const $card = $target.closest('.card');
|
||||
const entry = $card.data('entry');
|
||||
const ldapFieldMapping = getLdapFieldMapping();
|
||||
|
||||
App.Components.LdapImportModal.open(entry, ldapFieldMapping).done(() => {
|
||||
App.Layouts.Backend.displayNotification(lang('user_imported'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the no-records-found message
|
||||
*/
|
||||
function renderNoRecordsFound() {
|
||||
return $(`
|
||||
<div class="text-muted fst-italic">
|
||||
${lang('no_records_found')}
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the LDAP entry data on screen
|
||||
*
|
||||
* @param {Object} entry
|
||||
*/
|
||||
function renderEntry(entry) {
|
||||
if (!entry?.dn) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $entry = $(`
|
||||
<div class="card mb-2">
|
||||
<div class="card-header">
|
||||
${entry.dn}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="d-block mb-2">${lang('content')}</p>
|
||||
|
||||
<pre class="overflow-y-auto bg-light rounded p-2" style="max-height: 200px">${JSON.stringify(entry, null, 2)}</pre>
|
||||
|
||||
<div class="d-lg-flex">
|
||||
<button class="btn btn-outline-primary ldap-import ms-lg-auto">
|
||||
${lang('import')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
$entry.data('entry', entry);
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current connection settings and then search the directory based on the provided keyword.
|
||||
*
|
||||
* @param {Object} event
|
||||
*/
|
||||
function onSearchFormSubmit(event) {
|
||||
event.preventDefault();
|
||||
|
||||
saveSettings().done(() => {
|
||||
searchServer();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the module.
|
||||
*/
|
||||
function initialize() {
|
||||
$saveSettings.on('click', onSaveSettingsClick);
|
||||
$resetFilter.on('click', onResetFilterClick);
|
||||
$resetFieldMapping.on('click', onResetFieldMappingClick);
|
||||
$searchForm.on('submit', onSearchFormSubmit);
|
||||
$searchResults.on('click', '.ldap-import', onLdapImportClick);
|
||||
|
||||
const ldapSettings = vars('ldap_settings');
|
||||
|
||||
deserialize(ldapSettings);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', initialize);
|
||||
|
||||
return {};
|
||||
})();
|
|
@ -30,6 +30,7 @@ App.Pages.Providers = (function () {
|
|||
const $notes = $('#notes');
|
||||
const $language = $('#language');
|
||||
const $timezone = $('#timezone');
|
||||
const $ldapDn = $('#ldap-dn');
|
||||
const $username = $('#username');
|
||||
const $password = $('#password');
|
||||
const $passwordConfirmation = $('#password-confirm');
|
||||
|
@ -168,6 +169,7 @@ App.Pages.Providers = (function () {
|
|||
notes: $notes.val(),
|
||||
language: $language.val(),
|
||||
timezone: $timezone.val(),
|
||||
ldap_dn: $ldapDn.val(),
|
||||
settings: {
|
||||
username: $username.val(),
|
||||
working_plan: JSON.stringify(workingPlanManager.get()),
|
||||
|
@ -384,6 +386,7 @@ App.Pages.Providers = (function () {
|
|||
$notes.val(provider.notes);
|
||||
$language.val(provider.language);
|
||||
$timezone.val(provider.timezone);
|
||||
$ldapDn.val(provider.ldap_dn);
|
||||
|
||||
$username.val(provider.settings.username);
|
||||
$calendarView.val(provider.settings.calendar_view);
|
||||
|
|
|
@ -29,6 +29,7 @@ App.Pages.Secretaries = (function () {
|
|||
const $notes = $('#notes');
|
||||
const $language = $('#language');
|
||||
const $timezone = $('#timezone');
|
||||
const $ldapDn = $('#ldap-dn');
|
||||
const $username = $('#username');
|
||||
const $password = $('#password');
|
||||
const $passwordConfirmation = $('#password-confirm');
|
||||
|
@ -190,6 +191,7 @@ App.Pages.Secretaries = (function () {
|
|||
notes: $notes.val(),
|
||||
language: $language.val(),
|
||||
timezone: $timezone.val(),
|
||||
ldap_dn: $ldapDn.val(),
|
||||
settings: {
|
||||
username: $username.val(),
|
||||
notifications: Number($notifications.prop('checked')),
|
||||
|
@ -374,6 +376,7 @@ App.Pages.Secretaries = (function () {
|
|||
$notes.val(secretary.notes);
|
||||
$language.val(secretary.language);
|
||||
$timezone.val(secretary.timezone);
|
||||
$ldapDn.val(secretary.ldap_dn);
|
||||
|
||||
$username.val(secretary.settings.username);
|
||||
$calendarView.val(secretary.settings.calendar_view);
|
||||
|
|
|
@ -41,7 +41,7 @@ window.App.Utils.Message = (function () {
|
|||
text: lang('close'),
|
||||
className: 'btn btn-outline-primary',
|
||||
click: function (event, messageModal) {
|
||||
messageModal.dispose();
|
||||
messageModal.hide();
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
],
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"php": ">=8.1",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"monolog/monolog": "^2.8.0",
|
||||
"google/apiclient": "^2.12.6",
|
||||
"guzzlehttp/guzzle": "^7.5.0",
|
||||
"sabre/vobject": "^4.5"
|
||||
"sabre/vobject": "^4.5",
|
||||
},
|
||||
"require-dev": {
|
||||
"roave/security-advisories": "dev-master",
|
||||
|
|
27
openapi.yml
27
openapi.yml
|
@ -1936,6 +1936,8 @@ components:
|
|||
type: string
|
||||
customField5:
|
||||
type: string
|
||||
ldapDn:
|
||||
type: string
|
||||
notes:
|
||||
type: string
|
||||
example:
|
||||
|
@ -1953,6 +1955,7 @@ components:
|
|||
customField3: Value3
|
||||
customField4: Value4
|
||||
customField5: Value5
|
||||
ldapDn: null
|
||||
notes: This is a test customer.
|
||||
CustomerPayload:
|
||||
type: object
|
||||
|
@ -1985,6 +1988,8 @@ components:
|
|||
type: string
|
||||
customField5:
|
||||
type: string
|
||||
ldapDn:
|
||||
type: string
|
||||
notes:
|
||||
type: string
|
||||
example:
|
||||
|
@ -2001,6 +2006,7 @@ components:
|
|||
customField3: Value3
|
||||
customField4: Value4
|
||||
customField5: Value5
|
||||
ldapDn: null
|
||||
notes: This is a test customer.
|
||||
ServiceRecord:
|
||||
type: object
|
||||
|
@ -2122,6 +2128,10 @@ components:
|
|||
type: string
|
||||
timezone:
|
||||
type: string
|
||||
language:
|
||||
type: string
|
||||
ldapDn:
|
||||
type: string
|
||||
settings:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2146,6 +2156,8 @@ components:
|
|||
zip: '12345'
|
||||
notes: This is a test admin.
|
||||
timezone: UTC
|
||||
language: english
|
||||
ldapDn: null
|
||||
settings:
|
||||
username: jasondoe
|
||||
password: Password@123
|
||||
|
@ -2176,6 +2188,8 @@ components:
|
|||
type: string
|
||||
language:
|
||||
type: string
|
||||
ldapDn:
|
||||
type: string
|
||||
settings:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2200,6 +2214,7 @@ components:
|
|||
notes: This is a test admin.
|
||||
timezone: UTC
|
||||
language: english
|
||||
ldapDn: null
|
||||
settings:
|
||||
username: jasondoe
|
||||
password: Password@123
|
||||
|
@ -2234,6 +2249,8 @@ components:
|
|||
type: string
|
||||
isPrivate:
|
||||
type: boolean
|
||||
ldapDn:
|
||||
type: string
|
||||
services:
|
||||
type: array
|
||||
items:
|
||||
|
@ -2286,6 +2303,7 @@ components:
|
|||
language: english
|
||||
services: [ ]
|
||||
isPrivate: false
|
||||
ldapDn: null
|
||||
settings:
|
||||
username: chrisdoe
|
||||
password: Password@123
|
||||
|
@ -2351,6 +2369,8 @@ components:
|
|||
type: string
|
||||
isPrivate:
|
||||
type: boolean
|
||||
ldapDn:
|
||||
type: string
|
||||
services:
|
||||
type: array
|
||||
items:
|
||||
|
@ -2402,6 +2422,7 @@ components:
|
|||
timezone: UTC
|
||||
language: english
|
||||
isPrivate: false
|
||||
ldapDn: null
|
||||
services: [ ]
|
||||
settings:
|
||||
username: chrisdoe
|
||||
|
@ -2468,6 +2489,8 @@ components:
|
|||
type: string
|
||||
language:
|
||||
type: string
|
||||
ldapDn:
|
||||
type: string
|
||||
providers:
|
||||
type: array
|
||||
items:
|
||||
|
@ -2497,6 +2520,7 @@ components:
|
|||
notes: This is a test service.
|
||||
timezone: UTC
|
||||
language: english
|
||||
ldapDn: null
|
||||
providers: [ ]
|
||||
settings:
|
||||
username: jessydoe
|
||||
|
@ -2528,6 +2552,8 @@ components:
|
|||
type: string
|
||||
language:
|
||||
type: string
|
||||
ldapDn:
|
||||
type: string
|
||||
providers:
|
||||
type: array
|
||||
items:
|
||||
|
@ -2556,6 +2582,7 @@ components:
|
|||
notes: This is a test service.
|
||||
timezone: UTC
|
||||
language: english
|
||||
ldapDn: null
|
||||
providers: [ ]
|
||||
settings:
|
||||
username: jessydoe
|
||||
|
|
Loading…
Reference in a new issue