mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-02-06 12:31:37 +00:00
Merge branch 'staging' into feat/valkey
This commit is contained in:
@@ -71,6 +71,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
||||
// Init records array
|
||||
$spf_link = '<a href="http://www.open-spf.org/SPF_Record_Syntax/" target="_blank">SPF Record Syntax</a><br />';
|
||||
$dmarc_link = '<a href="https://www.kitterman.com/dmarc/assistant.html" target="_blank">DMARC Assistant</a>';
|
||||
$mtasts_report_link = '<a href="https://mxtoolbox.com/dmarc/smtp-tls/how-to-setup-smtp-tls-reports" target="_blank">TLS Report Record Syntax</a>';
|
||||
|
||||
$records = array();
|
||||
|
||||
@@ -128,6 +129,27 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
||||
);
|
||||
}
|
||||
|
||||
$mta_sts = mailbox('get', 'mta_sts', $domain);
|
||||
if (count($mta_sts) > 0 && $mta_sts['active'] == 1) {
|
||||
if (!in_array($domain, $alias_domains)) {
|
||||
$records[] = array(
|
||||
'mta-sts.' . $domain,
|
||||
'CNAME',
|
||||
$mailcow_hostname
|
||||
);
|
||||
}
|
||||
$records[] = array(
|
||||
'_mta-sts.' . $domain,
|
||||
'TXT',
|
||||
"v={$mta_sts['version']};id={$mta_sts['id']};",
|
||||
);
|
||||
$records[] = array(
|
||||
'_smtp._tls.' . $domain,
|
||||
'TXT',
|
||||
$mtasts_report_link,
|
||||
);
|
||||
}
|
||||
|
||||
$records[] = array(
|
||||
$domain,
|
||||
'TXT',
|
||||
@@ -341,15 +363,25 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
||||
}
|
||||
|
||||
foreach ($currents as &$current) {
|
||||
if ($current['type'] == "TXT" &&
|
||||
stripos(strtolower($current['txt']), 'v=sts') === 0) {
|
||||
if (strtolower($current[$data_field[$current['type']]]) == strtolower($record[2])) {
|
||||
$state = state_good;
|
||||
}
|
||||
else {
|
||||
$state = state_nomatch;
|
||||
}
|
||||
$state .= '<br />' . $current[$data_field[$current['type']]];
|
||||
}
|
||||
if ($current['type'] == 'TXT' &&
|
||||
stripos($current['txt'], 'v=dmarc') === 0 &&
|
||||
$record[2] == $dmarc_link) {
|
||||
stripos($current['txt'], 'v=dmarc') === 0 &&
|
||||
$record[2] == $dmarc_link) {
|
||||
$current['txt'] = str_replace(' ', '', $current['txt']);
|
||||
$state = $current[$data_field[$current['type']]] . state_optional;
|
||||
}
|
||||
elseif ($current['type'] == 'TXT' &&
|
||||
stripos($current['txt'], 'v=spf') === 0 &&
|
||||
$record[2] == $spf_link) {
|
||||
stripos($current['txt'], 'v=spf') === 0 &&
|
||||
$record[2] == $spf_link) {
|
||||
$state = state_nomatch;
|
||||
$rslt = get_spf_allowed_hosts($record[0], true);
|
||||
if (in_array($ip, $rslt) && in_array(expand_ipv6($ip6), $rslt)) {
|
||||
@@ -358,8 +390,8 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
||||
$state .= '<br />' . $current[$data_field[$current['type']]] . state_optional;
|
||||
}
|
||||
elseif ($current['type'] == 'TXT' &&
|
||||
stripos($current['txt'], 'v=dkim') === 0 &&
|
||||
stripos($record[2], 'v=dkim') === 0) {
|
||||
stripos($current['txt'], 'v=dkim') === 0 &&
|
||||
stripos($record[2], 'v=dkim') === 0) {
|
||||
preg_match('/v=DKIM1;.*k=rsa;.*p=([^;]*).*/i', $current[$data_field[$current['type']]], $dkim_matches_current);
|
||||
preg_match('/v=DKIM1;.*k=rsa;.*p=([^;]*).*/i', $record[2], $dkim_matches_good);
|
||||
if ($dkim_matches_current[1] == $dkim_matches_good[1]) {
|
||||
@@ -367,7 +399,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
||||
}
|
||||
}
|
||||
elseif ($current['type'] != 'TXT' &&
|
||||
isset($data_field[$current['type']]) && $state != state_good) {
|
||||
isset($data_field[$current['type']]) && $state != state_good) {
|
||||
$state = state_nomatch;
|
||||
if ($current[$data_field[$current['type']]] == $record[2]) {
|
||||
$state = state_good;
|
||||
|
||||
@@ -26,23 +26,25 @@ if (is_array($alertbox_log_parser)) {
|
||||
|
||||
// map tfa details for twig
|
||||
$pending_tfa_authmechs = [];
|
||||
foreach($_SESSION['pending_tfa_methods'] as $authdata){
|
||||
$pending_tfa_authmechs[$authdata['authmech']] = false;
|
||||
}
|
||||
if (isset($pending_tfa_authmechs['webauthn'])) {
|
||||
$pending_tfa_authmechs['webauthn'] = true;
|
||||
}
|
||||
if (!isset($pending_tfa_authmechs['webauthn'])
|
||||
&& isset($pending_tfa_authmechs['yubi_otp'])) {
|
||||
$pending_tfa_authmechs['yubi_otp'] = true;
|
||||
}
|
||||
if (!isset($pending_tfa_authmechs['webauthn'])
|
||||
&& !isset($pending_tfa_authmechs['yubi_otp'])
|
||||
&& isset($pending_tfa_authmechs['totp'])) {
|
||||
$pending_tfa_authmechs['totp'] = true;
|
||||
}
|
||||
if (isset($pending_tfa_authmechs['u2f'])) {
|
||||
$pending_tfa_authmechs['u2f'] = true;
|
||||
if (array_key_exists('pending_tfa_methods', $_SESSION)) {
|
||||
foreach($_SESSION['pending_tfa_methods'] as $authdata){
|
||||
$pending_tfa_authmechs[$authdata['authmech']] = false;
|
||||
}
|
||||
if (isset($pending_tfa_authmechs['webauthn'])) {
|
||||
$pending_tfa_authmechs['webauthn'] = true;
|
||||
}
|
||||
if (!isset($pending_tfa_authmechs['webauthn'])
|
||||
&& isset($pending_tfa_authmechs['yubi_otp'])) {
|
||||
$pending_tfa_authmechs['yubi_otp'] = true;
|
||||
}
|
||||
if (!isset($pending_tfa_authmechs['webauthn'])
|
||||
&& !isset($pending_tfa_authmechs['yubi_otp'])
|
||||
&& isset($pending_tfa_authmechs['totp'])) {
|
||||
$pending_tfa_authmechs['totp'] = true;
|
||||
}
|
||||
if (isset($pending_tfa_authmechs['u2f'])) {
|
||||
$pending_tfa_authmechs['u2f'] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// globals
|
||||
@@ -66,6 +68,8 @@ $globalVariables = [
|
||||
'lang_acl' => json_encode($lang['acl']),
|
||||
'lang_tfa' => json_encode($lang['tfa']),
|
||||
'lang_fido2' => json_encode($lang['fido2']),
|
||||
'lang_success' => json_encode($lang['success']),
|
||||
'lang_danger' => json_encode($lang['danger']),
|
||||
'docker_timeout' => $DOCKER_TIMEOUT,
|
||||
'session_lifetime' => (int)$SESSION_LIFETIME,
|
||||
'csrf_token' => $_SESSION['CSRF']['TOKEN'],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
function acl($_action, $_scope = null, $_data = null) {
|
||||
function acl($_action, $_scope = null, $_data = null, $_extra = null) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
$_data_log = $_data;
|
||||
@@ -24,7 +24,7 @@ function acl($_action, $_scope = null, $_data = null) {
|
||||
}
|
||||
// Users cannot change their own ACL
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)
|
||||
|| ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) {
|
||||
|| ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin' && $_SESSION['access_all_exception'] != '1')) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
@@ -34,7 +34,7 @@ function acl($_action, $_scope = null, $_data = null) {
|
||||
}
|
||||
// Read all available acl options by calling acl(get)
|
||||
// Set all available acl options we cannot find in the post data to 0, else 1
|
||||
$is_now = acl('get', 'user', $username);
|
||||
$is_now = acl('get', 'user', $username, $_extra);
|
||||
if (!empty($is_now)) {
|
||||
foreach ($is_now as $acl_now_name => $acl_now_val) {
|
||||
$set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
function app_passwd($_action, $_data = null) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
global $pdo;
|
||||
global $lang;
|
||||
$_data_log = $_data;
|
||||
!isset($_data_log['app_passwd']) ?: $_data_log['app_passwd'] = '*';
|
||||
!isset($_data_log['app_passwd2']) ?: $_data_log['app_passwd2'] = '*';
|
||||
@@ -43,20 +43,7 @@ function app_passwd($_action, $_data = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => 'password_complexity'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ($password != $password2) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => 'password_mismatch'
|
||||
);
|
||||
if (password_check($password, $password2) !== true) {
|
||||
return false;
|
||||
}
|
||||
$password_hashed = hash_password($password);
|
||||
@@ -88,15 +75,15 @@ function app_passwd($_action, $_data = null) {
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => 'app_passwd_added'
|
||||
);
|
||||
break;
|
||||
break;
|
||||
case 'edit':
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
$is_now = app_passwd('details', $id);
|
||||
if (!empty($is_now)) {
|
||||
$app_name = (!empty($_data['app_name'])) ? $_data['app_name'] : $is_now['name'];
|
||||
$password = (!empty($_data['password'])) ? $_data['password'] : null;
|
||||
$password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
|
||||
$password = (!empty($_data['app_passwd'])) ? $_data['app_passwd'] : null;
|
||||
$password2 = (!empty($_data['app_passwd2'])) ? $_data['app_passwd2'] : null;
|
||||
if (isset($_data['protocols'])) {
|
||||
$protocols = (array)$_data['protocols'];
|
||||
$imap_access = (in_array('imap_access', $protocols)) ? 1 : 0;
|
||||
@@ -126,20 +113,7 @@ function app_passwd($_action, $_data = null) {
|
||||
}
|
||||
$app_name = htmlspecialchars(trim($app_name));
|
||||
if (!empty($password) && !empty($password2)) {
|
||||
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'password_complexity'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if ($password != $password2) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'password_mismatch'
|
||||
);
|
||||
if (password_check($password, $password2) !== true) {
|
||||
continue;
|
||||
}
|
||||
$password_hashed = hash_password($password);
|
||||
@@ -182,7 +156,7 @@ function app_passwd($_action, $_data = null) {
|
||||
'msg' => array('object_modified', htmlspecialchars(implode(', ', $ids)))
|
||||
);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'delete':
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
@@ -213,19 +187,17 @@ function app_passwd($_action, $_data = null) {
|
||||
'msg' => array('app_passwd_removed', htmlspecialchars($id))
|
||||
);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'get':
|
||||
$app_passwds = array();
|
||||
$stmt = $pdo->prepare("SELECT `id`, `name` FROM `app_passwd` WHERE `mailbox` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$app_passwds = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
return $app_passwds;
|
||||
break;
|
||||
break;
|
||||
case 'details':
|
||||
$app_passwd_data = array();
|
||||
$stmt = $pdo->prepare("SELECT *
|
||||
FROM `app_passwd`
|
||||
WHERE `id` = :id");
|
||||
$stmt = $pdo->prepare("SELECT * FROM `app_passwd` WHERE `id` = :id");
|
||||
$stmt->execute(array(':id' => $_data));
|
||||
$app_passwd_data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (empty($app_passwd_data)) {
|
||||
@@ -237,6 +209,6 @@ function app_passwd($_action, $_data = null) {
|
||||
}
|
||||
$app_passwd_data['name'] = htmlspecialchars(trim($app_passwd_data['name']));
|
||||
return $app_passwd_data;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
740
data/web/inc/functions.auth.inc.php
Normal file
740
data/web/inc/functions.auth.inc.php
Normal file
@@ -0,0 +1,740 @@
|
||||
<?php
|
||||
function check_login($user, $pass, $app_passwd_data = false, $extra = null) {
|
||||
global $pdo;
|
||||
global $valkey;
|
||||
|
||||
$is_internal = $extra['is_internal'];
|
||||
$role = $extra['role'];
|
||||
|
||||
// Try validate admin
|
||||
if (!isset($role) || $role == "admin") {
|
||||
$result = admin_login($user, $pass);
|
||||
if ($result !== false){
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Try validate domain admin
|
||||
if (!isset($role) || $role == "domain_admin") {
|
||||
$result = domainadmin_login($user, $pass);
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try validate app password
|
||||
if (!isset($role) || $role == "app") {
|
||||
$result = apppass_login($user, $pass, $app_passwd_data);
|
||||
if ($result !== false) {
|
||||
if ($app_passwd_data['eas'] === true) {
|
||||
$service = 'EAS';
|
||||
} elseif ($app_passwd_data['dav'] === true) {
|
||||
$service = 'DAV';
|
||||
} else {
|
||||
$service = 'NONE';
|
||||
}
|
||||
$real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']);
|
||||
set_sasl_log($user, $real_rip, $service, $pass);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Try validate user
|
||||
if (!isset($role) || $role == "user") {
|
||||
$result = user_login($user, $pass);
|
||||
if ($result !== false) {
|
||||
if ($app_passwd_data['eas'] === true) {
|
||||
$service = 'EAS';
|
||||
} elseif ($app_passwd_data['dav'] === true) {
|
||||
$service = 'DAV';
|
||||
} else {
|
||||
$service = 'MAILCOWUI';
|
||||
}
|
||||
$real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']);
|
||||
set_sasl_log($user, $real_rip, $service);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// skip log and only return false if it's an internal request
|
||||
if ($is_internal == true) return false;
|
||||
|
||||
if (!isset($_SESSION['ldelay'])) {
|
||||
$_SESSION['ldelay'] = "0";
|
||||
$valkey->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
}
|
||||
elseif (!isset($_SESSION['mailcow_cc_username'])) {
|
||||
$_SESSION['ldelay'] = $_SESSION['ldelay']+0.5;
|
||||
$valkey->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'login_failed'
|
||||
);
|
||||
|
||||
sleep($_SESSION['ldelay']);
|
||||
return false;
|
||||
}
|
||||
|
||||
function admin_login($user, $pass){
|
||||
global $pdo;
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'malformed_username'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$user = strtolower(trim($user));
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
|
||||
WHERE `superadmin` = '1'
|
||||
AND `active` = '1'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// verify password
|
||||
if (verify_hash($row['password'], $pass)) {
|
||||
// check for tfa authenticators
|
||||
$authenticators = get_tfa($user);
|
||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
|
||||
// active tfa authenticators found, set pending user login
|
||||
$_SESSION['pending_mailcow_cc_username'] = $user;
|
||||
$_SESSION['pending_mailcow_cc_role'] = "admin";
|
||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||
unset($_SESSION['ldelay']);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'info',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'awaiting_tfa_confirmation'
|
||||
);
|
||||
return "pending";
|
||||
} else {
|
||||
unset($_SESSION['ldelay']);
|
||||
// Reactivate TFA if it was set to "deactivate TFA for next login"
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
return "admin";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function domainadmin_login($user, $pass){
|
||||
global $pdo;
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'malformed_username'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT `password` FROM `admin`
|
||||
WHERE `superadmin` = '0'
|
||||
AND `active`='1'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// verify password
|
||||
if (verify_hash($row['password'], $pass) !== false) {
|
||||
// check for tfa authenticators
|
||||
$authenticators = get_tfa($user);
|
||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0) {
|
||||
$_SESSION['pending_mailcow_cc_username'] = $user;
|
||||
$_SESSION['pending_mailcow_cc_role'] = "domainadmin";
|
||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||
unset($_SESSION['ldelay']);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'info',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'awaiting_tfa_confirmation'
|
||||
);
|
||||
return "pending";
|
||||
}
|
||||
else {
|
||||
unset($_SESSION['ldelay']);
|
||||
// Reactivate TFA if it was set to "deactivate TFA for next login"
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
return "domainadmin";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function user_login($user, $pass, $extra = null){
|
||||
global $pdo;
|
||||
global $iam_provider;
|
||||
global $iam_settings;
|
||||
|
||||
$is_internal = $extra['is_internal'];
|
||||
$service = $extra['service'];
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'malformed_username'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT
|
||||
mailbox.*,
|
||||
domain.active AS d_active
|
||||
FROM `mailbox`
|
||||
INNER JOIN domain on mailbox.domain = domain.domain
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// user does not exist, try call idp login and create user if possible via rest flow
|
||||
if (!$row){
|
||||
$result = false;
|
||||
if ($iam_settings['authsource'] == 'keycloak' && intval($iam_settings['mailpassword_flow']) == 1){
|
||||
$result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal, 'create' => true));
|
||||
} else if ($iam_settings['authsource'] == 'ldap') {
|
||||
$result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal, 'create' => true));
|
||||
}
|
||||
if ($result !== false){
|
||||
// double check if mailbox is active
|
||||
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
|
||||
INNER JOIN domain on mailbox.domain = domain.domain
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
AND `mailbox`.`active`='1'
|
||||
AND `domain`.`active`='1'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!empty($row)) {
|
||||
// check if user has access to service (imap, smtp, pop3, sieve) if service is set
|
||||
$row['attributes'] = json_decode($row['attributes'], true);
|
||||
if (isset($service)) {
|
||||
$key = strtolower($service) . "_access";
|
||||
if (isset($row['attributes'][$key]) && $row['attributes'][$key] != '1') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
clear_session();
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if user has access to service (imap, smtp, pop3, sieve) if service is set
|
||||
$row['attributes'] = json_decode($row['attributes'], true);
|
||||
if (isset($service)) {
|
||||
$key = strtolower($service) . "_access";
|
||||
if (isset($row['attributes'][$key]) && $row['attributes'][$key] != '1') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
switch ($row['authsource']) {
|
||||
case 'keycloak':
|
||||
// user authsource is keycloak, try using via rest flow
|
||||
if (intval($iam_settings['mailpassword_flow']) == 1){
|
||||
$result = keycloak_mbox_login_rest($user, $pass, array('is_internal' => $is_internal));
|
||||
if ($result !== false) {
|
||||
// double check if mailbox and domain is active
|
||||
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
|
||||
INNER JOIN domain on mailbox.domain = domain.domain
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
AND `mailbox`.`active`='1'
|
||||
AND `domain`.`active`='1'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (empty($row)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for tfa authenticators
|
||||
$authenticators = get_tfa($user);
|
||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
|
||||
// authenticators found, init TFA flow
|
||||
$_SESSION['pending_mailcow_cc_username'] = $user;
|
||||
$_SESSION['pending_mailcow_cc_role'] = "user";
|
||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||
unset($_SESSION['ldelay']);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Provider: Keycloak'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
return "pending";
|
||||
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
|
||||
// no authenticators found, login successfull
|
||||
if (!$is_internal){
|
||||
unset($_SESSION['ldelay']);
|
||||
// Reactivate TFA if it was set to "deactivate TFA for next login"
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Provider: Keycloak'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
}
|
||||
return "user";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'ldap':
|
||||
// user authsource is ldap
|
||||
$result = ldap_mbox_login($user, $pass, array('is_internal' => $is_internal));
|
||||
if ($result !== false) {
|
||||
// double check if mailbox and domain is active
|
||||
$stmt = $pdo->prepare("SELECT * FROM `mailbox`
|
||||
INNER JOIN domain on mailbox.domain = domain.domain
|
||||
WHERE `kind` NOT REGEXP 'location|thing|group'
|
||||
AND `mailbox`.`active`='1'
|
||||
AND `domain`.`active`='1'
|
||||
AND `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (empty($row)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for tfa authenticators
|
||||
$authenticators = get_tfa($user);
|
||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
|
||||
// authenticators found, init TFA flow
|
||||
$_SESSION['pending_mailcow_cc_username'] = $user;
|
||||
$_SESSION['pending_mailcow_cc_role'] = "user";
|
||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||
unset($_SESSION['ldelay']);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Provider: LDAP'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
return "pending";
|
||||
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
|
||||
// no authenticators found, login successfull
|
||||
if (!$is_internal){
|
||||
unset($_SESSION['ldelay']);
|
||||
// Reactivate TFA if it was set to "deactivate TFA for next login"
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Provider: LDAP'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
}
|
||||
return "user";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
break;
|
||||
case 'mailcow':
|
||||
if ($row['active'] != 1 || $row['d_active'] != 1) {
|
||||
return false;
|
||||
}
|
||||
// verify password
|
||||
if (verify_hash($row['password'], $pass) !== false) {
|
||||
|
||||
if (intval($row['attributes']['force_pw_update']) == 1) {
|
||||
$_SESSION['pending_pw_update'] = true;
|
||||
}
|
||||
|
||||
// check for tfa authenticators
|
||||
$authenticators = get_tfa($user);
|
||||
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
|
||||
// authenticators found, init TFA flow
|
||||
$_SESSION['pending_mailcow_cc_username'] = $user;
|
||||
$_SESSION['pending_mailcow_cc_role'] = "user";
|
||||
$_SESSION['pending_tfa_methods'] = $authenticators['additional'];
|
||||
unset($_SESSION['ldelay']);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Provider: mailcow'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
return "pending";
|
||||
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
|
||||
// no authenticators found, login successfull
|
||||
if (!$is_internal){
|
||||
unset($_SESSION['ldelay']);
|
||||
// Reactivate TFA if it was set to "deactivate TFA for next login"
|
||||
$stmt = $pdo->prepare("UPDATE `tfa` SET `active`='1' WHERE `username` = :user");
|
||||
$stmt->execute(array(':user' => $user));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Provider: mailcow'),
|
||||
'msg' => array('logged_in_as', $user)
|
||||
);
|
||||
}
|
||||
return "user";
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
function apppass_login($user, $pass, $app_passwd_data, $extra = null){
|
||||
global $pdo;
|
||||
|
||||
$is_internal = $extra['is_internal'];
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'malformed_username'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$protocol = false;
|
||||
if ($app_passwd_data['eas']){
|
||||
$protocol = 'eas';
|
||||
} else if ($app_passwd_data['dav']){
|
||||
$protocol = 'dav';
|
||||
} else if ($app_passwd_data['smtp']){
|
||||
$protocol = 'smtp';
|
||||
} else if ($app_passwd_data['imap']){
|
||||
$protocol = 'imap';
|
||||
} else if ($app_passwd_data['sieve']){
|
||||
$protocol = 'sieve';
|
||||
} else if ($app_passwd_data['pop3']){
|
||||
$protocol = 'pop3';
|
||||
} else if (!$is_internal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// fetch app password data
|
||||
$stmt = $pdo->prepare("SELECT `app_passwd`.*, `app_passwd`.`password` as `password`, `app_passwd`.`id` as `app_passwd_id` FROM `app_passwd`
|
||||
INNER JOIN `mailbox` ON `mailbox`.`username` = `app_passwd`.`mailbox`
|
||||
INNER JOIN `domain` ON `mailbox`.`domain` = `domain`.`domain`
|
||||
WHERE `mailbox`.`kind` NOT REGEXP 'location|thing|group'
|
||||
AND `mailbox`.`active` = '1'
|
||||
AND `domain`.`active` = '1'
|
||||
AND `app_passwd`.`active` = '1'
|
||||
AND `app_passwd`.`mailbox` = :user"
|
||||
);
|
||||
// fetch password data
|
||||
$stmt->execute(array(
|
||||
':user' => $user,
|
||||
));
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($rows as $row) {
|
||||
if ($protocol && $row[$protocol . '_access'] != '1'){
|
||||
continue;
|
||||
}
|
||||
|
||||
// verify password
|
||||
if (verify_hash($row['password'], $pass) !== false) {
|
||||
$_SESSION['app_passwd_id'] = $row['app_passwd_id'];
|
||||
unset($_SESSION['ldelay']);
|
||||
return "user";
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Keycloak REST Api Flow - auth user by mailcow_password attribute
|
||||
// This password will be used for direct UI, IMAP and SMTP Auth
|
||||
// To use direct user credentials, only Authorization Code Flow is valid
|
||||
function keycloak_mbox_login_rest($user, $pass, $extra = null){
|
||||
global $pdo;
|
||||
global $iam_provider;
|
||||
global $iam_settings;
|
||||
|
||||
$is_internal = $extra['is_internal'];
|
||||
$create = $extra['create'];
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'malformed_username'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!$iam_provider) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get access_token for service account of mailcow client
|
||||
$admin_token = identity_provider("get-keycloak-admin-token");
|
||||
|
||||
// get the mailcow_password attribute from keycloak user
|
||||
$url = "{$iam_settings['server_url']}/admin/realms/{$iam_settings['realm']}/users";
|
||||
$queryParams = array('email' => $user, 'exact' => true);
|
||||
$queryString = http_build_query($queryParams);
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 7);
|
||||
curl_setopt($curl, CURLOPT_URL, $url . '?' . $queryString);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
|
||||
'Authorization: Bearer ' . $admin_token,
|
||||
'Content-Type: application/json'
|
||||
));
|
||||
$user_res = json_decode(curl_exec($curl), true)[0];
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
curl_close($curl);
|
||||
if ($code != 200) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Identity Provider returned HTTP ' . $code),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!isset($user_res['attributes']['mailcow_password']) || !is_array($user_res['attributes']['mailcow_password'])){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'User has no mailcow_password attribute'),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($user_res['attributes']['mailcow_password'][0])){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', "User's mailcow_password attribute is empty"),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate mailcow_password
|
||||
$mailcow_password = $user_res['attributes']['mailcow_password'][0];
|
||||
if (!verify_hash($mailcow_password, $pass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get mapped template
|
||||
$user_template = $user_res['attributes']['mailcow_template'][0];
|
||||
$mapper_key = array_search($user_template, $iam_settings['mappers']);
|
||||
|
||||
if (!$create) {
|
||||
// login success
|
||||
if ($mapper_key !== false) {
|
||||
// update user
|
||||
$_SESSION['access_all_exception'] = '1';
|
||||
mailbox('edit', 'mailbox_from_template', array(
|
||||
'username' => $user,
|
||||
'name' => $user_res['name'],
|
||||
'template' => $iam_settings['templates'][$mapper_key]
|
||||
));
|
||||
$_SESSION['access_all_exception'] = '0';
|
||||
}
|
||||
return 'user';
|
||||
}
|
||||
|
||||
// check if login provisioning is enabled before creating user
|
||||
if (!$iam_settings['login_provisioning']){
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, "Auto-create users on login is deactivated"),
|
||||
'msg' => 'login_failed'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// check if matching attribute exist
|
||||
if (empty($iam_settings['mappers']) || !$user_template || $mapper_key === false) {
|
||||
if (!empty($iam_settings['default_template'])) {
|
||||
$mbox_template = $iam_settings['default_template'];
|
||||
} else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'No matching attribute mapping was found'),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$mbox_template = $iam_settings['templates'][$mapper_key];
|
||||
}
|
||||
|
||||
// create mailbox
|
||||
$_SESSION['access_all_exception'] = '1';
|
||||
$create_res = mailbox('add', 'mailbox_from_template', array(
|
||||
'domain' => explode('@', $user)[1],
|
||||
'local_part' => explode('@', $user)[0],
|
||||
'name' => $user_res['name'],
|
||||
'authsource' => 'keycloak',
|
||||
'template' => $mbox_template
|
||||
));
|
||||
$_SESSION['access_all_exception'] = '0';
|
||||
if (!$create_res){
|
||||
clear_session();
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Could not create mailbox on login'),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'user';
|
||||
}
|
||||
function ldap_mbox_login($user, $pass, $extra = null){
|
||||
global $pdo;
|
||||
global $iam_provider;
|
||||
global $iam_settings;
|
||||
|
||||
$is_internal = $extra['is_internal'];
|
||||
$create = $extra['create'];
|
||||
|
||||
if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*'),
|
||||
'msg' => 'malformed_username'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!$iam_provider) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$ldap_query = $iam_provider->query();
|
||||
if (!empty($iam_settings['filter'])) {
|
||||
$ldap_query = $ldap_query->rawFilter($iam_settings['filter']);
|
||||
}
|
||||
$ldap_query = $ldap_query->where($iam_settings['username_field'], '=', $user)
|
||||
->select([$iam_settings['username_field'], $iam_settings['attribute_field'], 'displayname', 'distinguishedname', 'dn']);
|
||||
|
||||
$user_res = $ldap_query->firstOrFail();
|
||||
} catch (Exception $e) {
|
||||
// clear $_SESSION['return'] to not leak data
|
||||
$_SESSION['return'] = array();
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', $e->getMessage()),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (!$iam_provider->auth()->attempt($user_res['dn'], $pass)) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
// clear $_SESSION['return'] to not leak data
|
||||
$_SESSION['return'] = array();
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', $e->getMessage()),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get mapped template
|
||||
$user_template = $user_res[$iam_settings['attribute_field']][0];
|
||||
$mapper_key = array_search($user_template, $iam_settings['mappers']);
|
||||
|
||||
if (!$create) {
|
||||
// login success
|
||||
if ($mapper_key !== false) {
|
||||
// update user
|
||||
$_SESSION['access_all_exception'] = '1';
|
||||
mailbox('edit', 'mailbox_from_template', array(
|
||||
'username' => $user,
|
||||
'name' => $user_res['displayname'][0],
|
||||
'template' => $iam_settings['templates'][$mapper_key]
|
||||
));
|
||||
$_SESSION['access_all_exception'] = '0';
|
||||
}
|
||||
return 'user';
|
||||
}
|
||||
|
||||
// check if login provisioning is enabled before creating user
|
||||
if (!$iam_settings['login_provisioning']){
|
||||
if (!$is_internal){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, "Auto-create users on login is deactivated"),
|
||||
'msg' => 'login_failed'
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// check if matching attribute exist
|
||||
if (empty($iam_settings['mappers']) || !$user_template || $mapper_key === false) {
|
||||
if (!empty($iam_settings['default_template'])) {
|
||||
$mbox_template = $iam_settings['default_template'];
|
||||
} else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'No matching attribute mapping was found'),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$mbox_template = $iam_settings['templates'][$mapper_key];
|
||||
}
|
||||
|
||||
// create mailbox
|
||||
$_SESSION['access_all_exception'] = '1';
|
||||
$create_res = mailbox('add', 'mailbox_from_template', array(
|
||||
'domain' => explode('@', $user)[1],
|
||||
'local_part' => explode('@', $user)[0],
|
||||
'name' => $user_res['displayname'][0],
|
||||
'authsource' => 'ldap',
|
||||
'template' => $mbox_template
|
||||
));
|
||||
$_SESSION['access_all_exception'] = '0';
|
||||
if (!$create_res){
|
||||
clear_session();
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $user, '*', 'Could not create mailbox on login'),
|
||||
'msg' => 'generic_server_error'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return 'user';
|
||||
}
|
||||
@@ -122,10 +122,16 @@ function customize($_action, $_item, $_data = null) {
|
||||
case 'app_links':
|
||||
$apps = (array)$_data['app'];
|
||||
$links = (array)$_data['href'];
|
||||
$user_links = (array)$_data['user_href'];
|
||||
$hide = (array)$_data['hide'];
|
||||
$out = array();
|
||||
if (count($apps) == count($links)) {
|
||||
if (count($apps) == count($links) && count($apps) == count($user_links) && count($apps) == count($hide)) {
|
||||
for ($i = 0; $i < count($apps); $i++) {
|
||||
$out[] = array($apps[$i] => $links[$i]);
|
||||
$out[] = array($apps[$i] => array(
|
||||
'link' => $links[$i],
|
||||
'user_link' => $user_links[$i],
|
||||
'hide' => ($hide[$i] === '0' || $hide[$i] === 0) ? false : true
|
||||
));
|
||||
}
|
||||
try {
|
||||
$valkey->set('APP_LINKS', json_encode($out));
|
||||
@@ -198,6 +204,35 @@ function customize($_action, $_item, $_data = null) {
|
||||
'msg' => 'ip_check_opt_in_modified'
|
||||
);
|
||||
break;
|
||||
case 'custom_login':
|
||||
$hide_user_quicklink = ($_data['hide_user_quicklink'] == "1") ? 1 : 0;
|
||||
$hide_domainadmin_quicklink = ($_data['hide_domainadmin_quicklink'] == "1") ? 1 : 0;
|
||||
$hide_admin_quicklink = ($_data['hide_admin_quicklink'] == "1") ? 1 : 0;
|
||||
$force_sso = ($_data['force_sso'] == "1") ? 1 : 0;
|
||||
|
||||
$custom_login = array(
|
||||
"hide_user_quicklink" => $hide_user_quicklink,
|
||||
"hide_domainadmin_quicklink" => $hide_domainadmin_quicklink,
|
||||
"hide_admin_quicklink" => $hide_admin_quicklink,
|
||||
"force_sso" => $force_sso,
|
||||
);
|
||||
try {
|
||||
$valkey->set('CUSTOM_LOGIN', json_encode($custom_login));
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => 'custom_login_modified'
|
||||
);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'delete':
|
||||
@@ -256,7 +291,23 @@ function customize($_action, $_item, $_data = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return ($app_links) ? $app_links : false;
|
||||
|
||||
if (empty($app_links)){
|
||||
return [];
|
||||
}
|
||||
|
||||
// convert from old style
|
||||
foreach($app_links as $i => $entry){
|
||||
foreach($entry as $app => $link){
|
||||
if (empty($link['link']) && empty($link['user_link'])){
|
||||
$app_links[$i][$app] = array();
|
||||
$app_links[$i][$app]['link'] = $link;
|
||||
$app_links[$i][$app]['user_link'] = $link;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $app_links;
|
||||
break;
|
||||
case 'main_logo':
|
||||
case 'main_logo_dark':
|
||||
@@ -274,8 +325,10 @@ function customize($_action, $_item, $_data = null) {
|
||||
break;
|
||||
case 'ui_texts':
|
||||
try {
|
||||
$data['title_name'] = ($title_name = $valkey->get('TITLE_NAME')) ? $title_name : 'mailcow UI';
|
||||
$data['main_name'] = ($main_name = $valkey->get('MAIN_NAME')) ? $main_name : 'mailcow UI';
|
||||
$mailcow_hostname = strtolower(getenv("MAILCOW_HOSTNAME"));
|
||||
|
||||
$data['title_name'] = ($title_name = $valkey->get('TITLE_NAME')) ? $title_name : "$mailcow_hostname - mail UI";
|
||||
$data['main_name'] = ($main_name = $valkey->get('MAIN_NAME')) ? $main_name : "$mailcow_hostname - mail UI";
|
||||
$data['apps_name'] = ($apps_name = $valkey->get('APPS_NAME')) ? $apps_name : $lang['header']['apps'];
|
||||
$data['help_text'] = ($help_text = $valkey->get('HELP_TEXT')) ? $help_text : false;
|
||||
if (!empty($valkey->get('UI_IMPRESS'))) {
|
||||
@@ -335,6 +388,20 @@ function customize($_action, $_item, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'custom_login':
|
||||
try {
|
||||
$custom_login = $valkey->get('CUSTOM_LOGIN');
|
||||
return $custom_login ? json_decode($custom_login, true) : array();
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -240,9 +240,12 @@ function dkim($_action, $_data = null, $privkey = false) {
|
||||
if (strlen($dkimdata['pubkey']) < 391) {
|
||||
$dkimdata['length'] = "1024";
|
||||
}
|
||||
elseif (strlen($dkimdata['pubkey']) < 736) {
|
||||
elseif (strlen($dkimdata['pubkey']) < 564) {
|
||||
$dkimdata['length'] = "2048";
|
||||
}
|
||||
elseif (strlen($dkimdata['pubkey']) < 736) {
|
||||
$dkimdata['length'] = "3072";
|
||||
}
|
||||
elseif (strlen($dkimdata['pubkey']) < 1416) {
|
||||
$dkimdata['length'] = "4096";
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
global $valkey;
|
||||
global $lang;
|
||||
global $MAILBOX_DEFAULT_ATTRIBUTES;
|
||||
global $iam_settings;
|
||||
|
||||
$_data_log = $_data;
|
||||
!isset($_data_log['password']) ?: $_data_log['password'] = '*';
|
||||
!isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
|
||||
@@ -682,15 +684,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
return true;
|
||||
break;
|
||||
case 'alias':
|
||||
$addresses = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
|
||||
$gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
|
||||
$active = intval($_data['active']);
|
||||
$sogo_visible = intval($_data['sogo_visible']);
|
||||
$goto_null = intval($_data['goto_null']);
|
||||
$goto_spam = intval($_data['goto_spam']);
|
||||
$goto_ham = intval($_data['goto_ham']);
|
||||
$addresses = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
|
||||
$gotos = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
|
||||
$internal = intval($_data['internal']);
|
||||
$active = intval($_data['active']);
|
||||
$sogo_visible = intval($_data['sogo_visible']);
|
||||
$goto_null = intval($_data['goto_null']);
|
||||
$goto_spam = intval($_data['goto_spam']);
|
||||
$goto_ham = intval($_data['goto_ham']);
|
||||
$private_comment = $_data['private_comment'];
|
||||
$public_comment = $_data['public_comment'];
|
||||
$public_comment = $_data['public_comment'];
|
||||
if (strlen($private_comment) > 160 | strlen($public_comment) > 160){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
@@ -840,8 +843,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `active`)
|
||||
VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :active)");
|
||||
$stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `internal`, `active`)
|
||||
VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :internal, :active)");
|
||||
if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) {
|
||||
$stmt->execute(array(
|
||||
':address' => '@'.$domain,
|
||||
@@ -851,6 +854,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
':goto' => $goto,
|
||||
':domain' => $domain,
|
||||
':sogo_visible' => $sogo_visible,
|
||||
':internal' => $internal,
|
||||
':active' => $active
|
||||
));
|
||||
}
|
||||
@@ -862,6 +866,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
':goto' => $goto,
|
||||
':domain' => $domain,
|
||||
':sogo_visible' => $sogo_visible,
|
||||
':internal' => $internal,
|
||||
':active' => $active
|
||||
));
|
||||
}
|
||||
@@ -1005,6 +1010,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$local_part = strtolower(trim($_data['local_part']));
|
||||
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
$username = $local_part . '@' . $domain;
|
||||
$authsource = 'mailcow';
|
||||
if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
@@ -1021,15 +1027,19 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ($_data['authsource'] == "mailcow" ||
|
||||
in_array($_data['authsource'], array('keycloak', 'generic-oidc', 'ldap')) && $iam_settings['authsource'] == $_data['authsource']){
|
||||
$authsource = $_data['authsource'];
|
||||
}
|
||||
if (empty($name)) {
|
||||
$name = $local_part;
|
||||
}
|
||||
$template_attr = null;
|
||||
if ($_data['template']){
|
||||
$template_attr = mailbox('get', 'mailbox_templates', $_data['template'])['attributes'];
|
||||
$template_attr = mailbox('get', 'mailbox_templates', $_data['template'], $_extra)['attributes'];
|
||||
}
|
||||
if (empty($template_attr)) {
|
||||
$template_attr = mailbox('get', 'mailbox_templates')[0]['attributes'];
|
||||
$template_attr = mailbox('get', 'mailbox_templates', null, $_extra)[0]['attributes'];
|
||||
}
|
||||
$MAILBOX_DEFAULT_ATTRIBUTES = array_merge($MAILBOX_DEFAULT_ATTRIBUTES, $template_attr);
|
||||
|
||||
@@ -1038,7 +1048,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$name = ltrim(rtrim($_data['name'], '>'), '<');
|
||||
$tags = (isset($_data['tags'])) ? $_data['tags'] : $MAILBOX_DEFAULT_ATTRIBUTES['tags'];
|
||||
$quota_m = (isset($_data['quota'])) ? intval($_data['quota']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['quota']) / 1024 ** 2;
|
||||
if ((!isset($_SESSION['acl']['unlimited_quota']) || $_SESSION['acl']['unlimited_quota'] != "1") && $quota_m === 0) {
|
||||
if ($authsource != 'mailcow'){
|
||||
$password = '';
|
||||
$password2 = '';
|
||||
$password_hashed = '';
|
||||
}
|
||||
if (!hasACLAccess("unlimited_quota") && $quota_m === 0) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1067,6 +1082,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
|
||||
$quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
|
||||
$quota_b = ($quota_m * 1048576);
|
||||
$attribute_hash = (!empty($_data['attribute_hash'])) ? $_data['attribute_hash'] : '';
|
||||
if (in_array($authsource, array('keycloak', 'generic-oidc', 'ldap'))){
|
||||
$force_pw_update = 0;
|
||||
}
|
||||
$mailbox_attrs = json_encode(
|
||||
array(
|
||||
'force_pw_update' => strval($force_pw_update),
|
||||
@@ -1081,7 +1100,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'passwd_update' => time(),
|
||||
'mailbox_format' => strval($MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format']),
|
||||
'quarantine_notification' => strval($quarantine_notification),
|
||||
'quarantine_category' => strval($quarantine_category)
|
||||
'quarantine_category' => strval($quarantine_category),
|
||||
'attribute_hash' => $attribute_hash
|
||||
)
|
||||
);
|
||||
if (!is_valid_domain_name($domain)) {
|
||||
@@ -1156,10 +1176,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (password_check($password, $password2) !== true) {
|
||||
return false;
|
||||
if ($authsource == 'mailcow'){
|
||||
if (password_check($password, $password2) !== true) {
|
||||
return false;
|
||||
}
|
||||
$password_hashed = hash_password($password);
|
||||
}
|
||||
$password_hashed = hash_password($password);
|
||||
if ($MailboxData['count'] >= $DomainData['mailboxes']) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
@@ -1185,8 +1207,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `quota`, `local_part`, `domain`, `attributes`, `active`)
|
||||
VALUES (:username, :password_hashed, :name, :quota_b, :local_part, :domain, :mailbox_attrs, :active)");
|
||||
$stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `quota`, `local_part`, `domain`, `attributes`, `authsource`, `active`)
|
||||
VALUES (:username, :password_hashed, :name, :quota_b, :local_part, :domain, :mailbox_attrs, :authsource, :active)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':password_hashed' => $password_hashed,
|
||||
@@ -1195,6 +1217,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
':local_part' => $local_part,
|
||||
':domain' => $domain,
|
||||
':mailbox_attrs' => $mailbox_attrs,
|
||||
':authsource' => $authsource,
|
||||
':active' => $active
|
||||
));
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET
|
||||
@@ -1203,6 +1226,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
));
|
||||
// save delimiter_action
|
||||
if (isset($_data['tagged_mail_handler'])) {
|
||||
mailbox('edit', 'delimiter_action', array(
|
||||
'username' => $username,
|
||||
'tagged_mail_handler' => $_data['tagged_mail_handler']
|
||||
));
|
||||
}
|
||||
|
||||
// save tags
|
||||
foreach($tags as $index => $tag){
|
||||
if (empty($tag)) continue;
|
||||
@@ -1214,11 +1245,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
break;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `tags_mailbox` (`username`, `tag_name`) VALUES (:username, :tag_name)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':tag_name' => $tag,
|
||||
));
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `tags_mailbox` (`username`, `tag_name`) VALUES (:username, :tag_name)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':tag_name' => $tag,
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `quota2` (`username`, `bytes`, `messages`)
|
||||
VALUES (:username, '0', '0') ON DUPLICATE KEY UPDATE `bytes` = '0', `messages` = '0';");
|
||||
@@ -1312,16 +1346,136 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'object' => $username,
|
||||
'rl_frame' => $_data['rl_frame'],
|
||||
'rl_value' => $_data['rl_value']
|
||||
));
|
||||
), $_extra);
|
||||
}
|
||||
|
||||
update_sogo_static_view($username);
|
||||
try {
|
||||
update_sogo_static_view($username);
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => array('mailbox_added', htmlspecialchars($username))
|
||||
);
|
||||
return true;
|
||||
break;
|
||||
case 'mailbox_from_template':
|
||||
$stmt = $pdo->prepare("SELECT * FROM `templates`
|
||||
WHERE `template` = :template AND type = 'mailbox'");
|
||||
$stmt->execute(array(
|
||||
":template" => $_data['template']
|
||||
));
|
||||
$mbox_template_data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (empty($mbox_template_data)){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'template_missing'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$attribute_hash = sha1(json_encode($mbox_template_data["attributes"]));
|
||||
$mbox_template_data = json_decode($mbox_template_data["attributes"], true);
|
||||
$mbox_template_data['domain'] = $_data['domain'];
|
||||
$mbox_template_data['name'] = $_data['name'];
|
||||
$mbox_template_data['local_part'] = $_data['local_part'];
|
||||
$mbox_template_data['authsource'] = $_data['authsource'];
|
||||
$mbox_template_data['attribute_hash'] = $attribute_hash;
|
||||
$mbox_template_data['quota'] = intval($mbox_template_data['quota'] / 1048576);
|
||||
|
||||
$mailbox_attributes = array('acl' => array());
|
||||
foreach ($mbox_template_data as $key => $value){
|
||||
switch (true) {
|
||||
case (strpos($key, 'acl_') === 0 && $value != 0):
|
||||
array_push($mailbox_attributes['acl'], str_replace('acl_' , '', $key));
|
||||
break;
|
||||
default:
|
||||
$mailbox_attributes[$key] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mailbox('add', 'mailbox', $mailbox_attributes);
|
||||
break;
|
||||
case 'mta_sts':
|
||||
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
$version = strtolower($_data['version']);
|
||||
$mode = strtolower($_data['mode']);
|
||||
$mx = explode(",", preg_replace('/\s+/', '', $_data['mx']));
|
||||
$max_age = intval($_data['max_age']);
|
||||
$active = (intval($_data['active']) == 1) ? 1 : 0;
|
||||
$id = date('YmdHis');
|
||||
|
||||
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($version) || !in_array($version, array('stsv1'))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('version_invalid', htmlspecialchars($domain))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($mode) || !in_array($mode, array('enforce', 'testing', 'none'))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('mode_invalid', htmlspecialchars($domain))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (empty($max_age) || $max_age < 0 || $max_age > 31536000) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('max_age_invalid', htmlspecialchars($domain))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
foreach ($mx as $index => $mx_domain) {
|
||||
$mx_domain = idn_to_ascii(strtolower(trim($mx_domain)), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
if (!is_valid_domain_name($mx_domain, array('allow_wildcard' => true))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('mx_invalid', htmlspecialchars($mx_domain))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `mta_sts` (`id`, `domain`, `version`, `mode`, `mx`, `max_age`, `active`)
|
||||
VALUES (:id, :domain, :version, :mode, :mx, :max_age, :active)");
|
||||
$stmt->execute(array(
|
||||
':id' => $id,
|
||||
':domain' => $domain,
|
||||
':version' => $version,
|
||||
':mode' => $mode,
|
||||
':mx' => implode(",", $mx),
|
||||
':max_age' => $max_age,
|
||||
':active' => $active
|
||||
));
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'resource':
|
||||
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
@@ -1544,6 +1698,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$attr = array();
|
||||
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
|
||||
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
|
||||
$attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler']);
|
||||
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
|
||||
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
|
||||
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
|
||||
@@ -1689,7 +1844,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
else {
|
||||
$usernames = $_data['username'];
|
||||
}
|
||||
if (!isset($_SESSION['acl']['tls_policy']) || $_SESSION['acl']['tls_policy'] != "1" ) {
|
||||
if (!hasACLAccess("tls_policy")) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1698,7 +1853,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
return false;
|
||||
}
|
||||
foreach ($usernames as $username) {
|
||||
if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1706,7 +1861,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$is_now = mailbox('get', 'tls_policy', $username);
|
||||
$is_now = mailbox('get', 'tls_policy', $username, $_extra);
|
||||
if (!empty($is_now)) {
|
||||
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
|
||||
$tls_enforce_out = (isset($_data['tls_enforce_out'])) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out'];
|
||||
@@ -1743,7 +1898,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
else {
|
||||
$usernames = $_data['username'];
|
||||
}
|
||||
if (!isset($_SESSION['acl']['quarantine_notification']) || $_SESSION['acl']['quarantine_notification'] != "1" ) {
|
||||
if (!hasACLAccess("quarantine_notification")) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1752,7 +1907,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
return false;
|
||||
}
|
||||
foreach ($usernames as $username) {
|
||||
if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1760,7 +1915,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$is_now = mailbox('get', 'quarantine_notification', $username);
|
||||
$is_now = mailbox('get', 'quarantine_notification', $username, $_extra);
|
||||
if (!empty($is_now)) {
|
||||
$quarantine_notification = (isset($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
|
||||
}
|
||||
@@ -1802,7 +1957,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
else {
|
||||
$usernames = $_data['username'];
|
||||
}
|
||||
if (!isset($_SESSION['acl']['quarantine_category']) || $_SESSION['acl']['quarantine_category'] != "1" ) {
|
||||
if (!hasACLAccess("quarantine_category")) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1811,7 +1966,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
return false;
|
||||
}
|
||||
foreach ($usernames as $username) {
|
||||
if (!filter_var($username, FILTER_VALIDATE_EMAIL) || !hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -1819,7 +1974,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$is_now = mailbox('get', 'quarantine_category', $username);
|
||||
$is_now = mailbox('get', 'quarantine_category', $username, $_extra);
|
||||
if (!empty($is_now)) {
|
||||
$quarantine_category = (isset($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
|
||||
}
|
||||
@@ -2329,6 +2484,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
foreach ($ids as $id) {
|
||||
$is_now = mailbox('get', 'alias_details', $id);
|
||||
if (!empty($is_now)) {
|
||||
$internal = (isset($_data['internal'])) ? intval($_data['internal']) : $is_now['internal'];
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
$sogo_visible = (isset($_data['sogo_visible'])) ? intval($_data['sogo_visible']) : $is_now['sogo_visible'];
|
||||
$goto_null = (isset($_data['goto_null'])) ? intval($_data['goto_null']) : 0;
|
||||
@@ -2514,6 +2670,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
`domain` = :domain,
|
||||
`goto` = :goto,
|
||||
`sogo_visible`= :sogo_visible,
|
||||
`internal`= :internal,
|
||||
`active`= :active
|
||||
WHERE `id` = :id");
|
||||
$stmt->execute(array(
|
||||
@@ -2523,6 +2680,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
':domain' => $domain,
|
||||
':goto' => $goto,
|
||||
':sogo_visible' => $sogo_visible,
|
||||
':internal' => $internal,
|
||||
':active' => $active,
|
||||
':id' => $is_now['id']
|
||||
));
|
||||
@@ -2863,7 +3021,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$is_now = mailbox('get', 'mailbox_details', $username);
|
||||
$is_now = mailbox('get', 'mailbox_details', $username, $_extra);
|
||||
if (isset($_data['protocol_access'])) {
|
||||
$_data['protocol_access'] = (array)$_data['protocol_access'];
|
||||
$_data['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0;
|
||||
@@ -2874,20 +3032,29 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
if (!empty($is_now)) {
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
(int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
|
||||
(int)$sogo_access = (isset($_data['sogo_access']) && isset($_SESSION['acl']['sogo_access']) && $_SESSION['acl']['sogo_access'] == "1") ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
|
||||
(int)$imap_access = (isset($_data['imap_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
|
||||
(int)$pop3_access = (isset($_data['pop3_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
|
||||
(int)$smtp_access = (isset($_data['smtp_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
|
||||
(int)$sieve_access = (isset($_data['sieve_access']) && isset($_SESSION['acl']['protocol_access']) && $_SESSION['acl']['protocol_access'] == "1") ? intval($_data['sieve_access']) : intval($is_now['attributes']['sieve_access']);
|
||||
(int)$relayhost = (isset($_data['relayhost']) && isset($_SESSION['acl']['mailbox_relayhost']) && $_SESSION['acl']['mailbox_relayhost'] == "1") ? intval($_data['relayhost']) : intval($is_now['attributes']['relayhost']);
|
||||
(int)$sogo_access = (isset($_data['sogo_access']) && hasACLAccess("sogo_access")) ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
|
||||
(int)$imap_access = (isset($_data['imap_access']) && hasACLAccess("protocol_access")) ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
|
||||
(int)$pop3_access = (isset($_data['pop3_access']) && hasACLAccess("protocol_access")) ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
|
||||
(int)$smtp_access = (isset($_data['smtp_access']) && hasACLAccess("protocol_access")) ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
|
||||
(int)$sieve_access = (isset($_data['sieve_access']) && hasACLAccess("protocol_access")) ? intval($_data['sieve_access']) : intval($is_now['attributes']['sieve_access']);
|
||||
(int)$relayhost = (isset($_data['relayhost']) && hasACLAccess("mailbox_relayhost")) ? intval($_data['relayhost']) : intval($is_now['attributes']['relayhost']);
|
||||
(int)$quota_m = (isset_has_content($_data['quota'])) ? intval($_data['quota']) : ($is_now['quota'] / 1048576);
|
||||
$name = (!empty($_data['name'])) ? ltrim(rtrim($_data['name'], '>'), '<') : $is_now['name'];
|
||||
$domain = $is_now['domain'];
|
||||
$quota_b = $quota_m * 1048576;
|
||||
$password = (!empty($_data['password'])) ? $_data['password'] : null;
|
||||
$password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
|
||||
$pw_recovery_email = (isset($_data['pw_recovery_email'])) ? $_data['pw_recovery_email'] : $is_now['attributes']['recovery_email'];
|
||||
$tags = (is_array($_data['tags']) ? $_data['tags'] : array());
|
||||
$attribute_hash = (!empty($_data['attribute_hash'])) ? $_data['attribute_hash'] : '';
|
||||
$authsource = $is_now['authsource'];
|
||||
if ($_data['authsource'] == "mailcow" ||
|
||||
in_array($_data['authsource'], array('keycloak', 'generic-oidc', 'ldap')) && $iam_settings['authsource'] == $_data['authsource']){
|
||||
$authsource = $_data['authsource'];
|
||||
}
|
||||
if (in_array($authsource, array('keycloak', 'generic-oidc', 'ldap'))){
|
||||
$force_pw_update = 0;
|
||||
}
|
||||
$pw_recovery_email = (isset($_data['pw_recovery_email']) && $authsource == 'mailcow') ? $_data['pw_recovery_email'] : $is_now['attributes']['recovery_email'];
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -2898,7 +3065,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
continue;
|
||||
}
|
||||
// if already 0 == ok
|
||||
if ((!isset($_SESSION['acl']['unlimited_quota']) || $_SESSION['acl']['unlimited_quota'] != "1") && ($quota_m == 0 && $is_now['quota'] != 0)) {
|
||||
if (!hasACLAccess("unlimited_quota") && ($quota_m == 0 && $is_now['quota'] != 0)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -2914,7 +3081,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$DomainData = mailbox('get', 'domain_details', $domain);
|
||||
$DomainData = mailbox('get', 'domain_details', $domain, $_extra);
|
||||
if ($quota_m > ($is_now['max_new_quota'] / 1048576)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
@@ -2933,7 +3100,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
}
|
||||
$extra_acls = array();
|
||||
if (isset($_data['extended_sender_acl'])) {
|
||||
if (!isset($_SESSION['acl']['extend_sender_acl']) || $_SESSION['acl']['extend_sender_acl'] != "1" ) {
|
||||
if (!hasACLAccess("extend_sender_acl")) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -3126,7 +3293,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET
|
||||
`password` = :password_hashed,
|
||||
`attributes` = JSON_SET(`attributes`, '$.passwd_update', NOW())
|
||||
WHERE `username` = :username");
|
||||
WHERE `username` = :username AND authsource = 'mailcow'");
|
||||
$stmt->execute(array(
|
||||
':password_hashed' => $password_hashed,
|
||||
':username' => $username
|
||||
@@ -3145,6 +3312,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
`active` = :active,
|
||||
`name`= :name,
|
||||
`quota` = :quota_b,
|
||||
`authsource` = :authsource,
|
||||
`attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update),
|
||||
`attributes` = JSON_SET(`attributes`, '$.sogo_access', :sogo_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
|
||||
@@ -3152,22 +3320,25 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
`attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.relayhost', :relayhost),
|
||||
`attributes` = JSON_SET(`attributes`, '$.smtp_access', :smtp_access),
|
||||
`attributes` = JSON_SET(`attributes`, '$.recovery_email', :recovery_email)
|
||||
`attributes` = JSON_SET(`attributes`, '$.recovery_email', :recovery_email),
|
||||
`attributes` = JSON_SET(`attributes`, '$.attribute_hash', :attribute_hash)
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':active' => $active,
|
||||
':name' => $name,
|
||||
':quota_b' => $quota_b,
|
||||
':force_pw_update' => $force_pw_update,
|
||||
':sogo_access' => $sogo_access,
|
||||
':imap_access' => $imap_access,
|
||||
':pop3_access' => $pop3_access,
|
||||
':sieve_access' => $sieve_access,
|
||||
':smtp_access' => $smtp_access,
|
||||
':recovery_email' => $pw_recovery_email,
|
||||
':relayhost' => $relayhost,
|
||||
':username' => $username
|
||||
));
|
||||
$stmt->execute(array(
|
||||
':active' => $active,
|
||||
':name' => $name,
|
||||
':quota_b' => $quota_b,
|
||||
':attribute_hash' => $attribute_hash,
|
||||
':force_pw_update' => $force_pw_update,
|
||||
':sogo_access' => $sogo_access,
|
||||
':imap_access' => $imap_access,
|
||||
':pop3_access' => $pop3_access,
|
||||
':sieve_access' => $sieve_access,
|
||||
':smtp_access' => $smtp_access,
|
||||
':recovery_email' => $pw_recovery_email,
|
||||
':relayhost' => $relayhost,
|
||||
':username' => $username,
|
||||
':authsource' => $authsource
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -3177,6 +3348,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// save delimiter_action
|
||||
if (isset($_data['tagged_mail_handler'])) {
|
||||
mailbox('edit', 'delimiter_action', array(
|
||||
'username' => $username,
|
||||
'tagged_mail_handler' => $_data['tagged_mail_handler']
|
||||
));
|
||||
}
|
||||
// save tags
|
||||
foreach($tags as $index => $tag){
|
||||
if (empty($tag)) continue;
|
||||
@@ -3188,11 +3366,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
);
|
||||
break;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `tags_mailbox` (`username`, `tag_name`) VALUES (:username, :tag_name)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':tag_name' => $tag,
|
||||
));
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `tags_mailbox` (`username`, `tag_name`) VALUES (:username, :tag_name)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':tag_name' => $tag,
|
||||
));
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -3201,7 +3382,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'msg' => array('mailbox_modified', $username)
|
||||
);
|
||||
|
||||
update_sogo_static_view($username);
|
||||
try {
|
||||
update_sogo_static_view($username);
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
@@ -3231,7 +3420,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
}
|
||||
|
||||
$is_now = mailbox('get', 'mailbox_details', $old_username);
|
||||
if (empty($is_now)) {
|
||||
if (empty($is_now) || ($is_now['active'] != '1' && $is_now['active'] != '2')) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -3401,6 +3590,75 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'msg' => array('mailbox_renamed', $old_username, $new_username)
|
||||
);
|
||||
break;
|
||||
case 'mailbox_from_template':
|
||||
$stmt = $pdo->prepare("SELECT * FROM `templates`
|
||||
WHERE `template` = :template AND type = 'mailbox'");
|
||||
$stmt->execute(array(
|
||||
":template" => $_data['template']
|
||||
));
|
||||
$mbox_template_data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (empty($mbox_template_data)){
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'template_missing'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
$attribute_hash = sha1(json_encode($mbox_template_data["attributes"]));
|
||||
$is_now = mailbox('get', 'mailbox_details', $_data['username']);
|
||||
$name = ltrim(rtrim($_data['name'], '>'), '<');
|
||||
if ($is_now['attributes']['attribute_hash'] == $attribute_hash && $is_now['name'] == $name)
|
||||
return true;
|
||||
|
||||
$mbox_template_data = json_decode($mbox_template_data["attributes"], true);
|
||||
$mbox_template_data['attribute_hash'] = $attribute_hash;
|
||||
$mbox_template_data['name'] = $name;
|
||||
$quarantine_attributes = array('username' => $_data['username']);
|
||||
$tls_attributes = array('username' => $_data['username']);
|
||||
$ratelimit_attributes = array('object' => $_data['username']);
|
||||
$acl_attributes = array('username' => $_data['username'], 'user_acl' => array());
|
||||
$mailbox_attributes = array('username' => $_data['username']);
|
||||
foreach ($mbox_template_data as $key => $value){
|
||||
switch (true) {
|
||||
case (strpos($key, 'quarantine_') === 0):
|
||||
$quarantine_attributes[$key] = $value;
|
||||
break;
|
||||
case (strpos($key, 'tls_') === 0):
|
||||
if ($value == null)
|
||||
$value = 0;
|
||||
$tls_attributes[$key] = $value;
|
||||
break;
|
||||
case (strpos($key, 'rl_') === 0):
|
||||
$ratelimit_attributes[$key] = $value;
|
||||
break;
|
||||
case (strpos($key, 'acl_') === 0 && $value != 0):
|
||||
array_push($acl_attributes['user_acl'], str_replace('acl_' , '', $key));
|
||||
break;
|
||||
default:
|
||||
$mailbox_attributes[$key] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$mailbox_attributes['quota'] = intval($mailbox_attributes['quota'] / 1048576);
|
||||
$result = mailbox('edit', 'mailbox', $mailbox_attributes);
|
||||
if ($result === false) return $result;
|
||||
$result = mailbox('edit', 'tls_policy', $tls_attributes);
|
||||
if ($result === false) return $result;
|
||||
$result = mailbox('edit', 'quarantine_notification', $quarantine_attributes);
|
||||
if ($result === false) return $result;
|
||||
$result = mailbox('edit', 'quarantine_category', $quarantine_attributes);
|
||||
if ($result === false) return $result;
|
||||
$result = ratelimit('edit', 'mailbox', $ratelimit_attributes);
|
||||
if ($result === false) return $result;
|
||||
$result = acl('edit', 'user', $acl_attributes);
|
||||
if ($result === false) return $result;
|
||||
|
||||
$_SESSION['return'] = array();
|
||||
return true;
|
||||
break;
|
||||
case 'mailbox_templates':
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'][] = array(
|
||||
@@ -3442,6 +3700,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$attr = array();
|
||||
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
|
||||
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags'];
|
||||
$attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : $is_now['tagged_mail_handler'];
|
||||
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
|
||||
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
|
||||
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame'];
|
||||
@@ -3562,6 +3821,125 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
|
||||
return true;
|
||||
break;
|
||||
case 'mta_sts':
|
||||
if (!is_array($_data['domains'])) {
|
||||
$domains = array();
|
||||
$domains[] = $_data['domains'];
|
||||
}
|
||||
else {
|
||||
$domains = $_data['domains'];
|
||||
}
|
||||
|
||||
foreach ($domains as $domain) {
|
||||
$domain = idn_to_ascii(strtolower(trim($domain)), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
|
||||
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$is_now = mailbox('get', 'mta_sts', $domain);
|
||||
if (!empty($is_now)) {
|
||||
$version = (isset($_data['version'])) ? strtolower($_data['version']) : $is_now['version'];
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||
$active = ($active == 1) ? 1 : 0;
|
||||
$mode = (isset($_data['mode'])) ? strtolower($_data['mode']) : $is_now['mode'];
|
||||
$mx = (isset($_data['mx'])) ? explode(",", preg_replace('/\s+/', '', $_data['mx'])) : $is_now['mx'];
|
||||
$max_age = (isset($_data['max_age'])) ? intval($_data['max_age']) : $is_now['max_age'];
|
||||
|
||||
// Update ID if neccesary
|
||||
if ($version != strtolower($is_now['version']) ||
|
||||
$mode != strtolower($is_now['mode']) ||
|
||||
$mx != $is_now['mx'] ||
|
||||
$max_age != $is_now['max_age']) {
|
||||
$id = date('YmdHis');
|
||||
} else {
|
||||
$id = $is_now['id'];
|
||||
}
|
||||
|
||||
} else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($version) || !in_array($version, array('stsv1'))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('version_invalid', htmlspecialchars($version))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (empty($mode) || !in_array($mode, array('enforce', 'testing', 'none'))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('mode_invalid', htmlspecialchars($domain))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (empty($max_age) || $max_age < 0 || $max_age > 31557600) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('max_age_invalid', htmlspecialchars($domain))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
foreach ($mx as $index => $mx_domain) {
|
||||
$mx_domain = idn_to_ascii(strtolower(trim($mx_domain)), 0, INTL_IDNA_VARIANT_UTS46);
|
||||
$invalid_mx = false;
|
||||
if (!is_valid_domain_name($mx_domain, array('allow_wildcard' => true))) {
|
||||
$invalid_mx = $mx_domain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($invalid_mx) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('mx_invalid', htmlspecialchars($invalid_mx))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `mta_sts` SET `id` = :id, `version` = :version, `mode` = :mode, `mx` = :mx, `max_age` = :max_age, `active` = :active WHERE `domain` = :domain");
|
||||
$stmt->execute(array(
|
||||
':id' => $id,
|
||||
':domain' => $domain,
|
||||
':version' => $version,
|
||||
':mode' => $mode,
|
||||
':mx' => implode(",", $mx),
|
||||
':max_age' => $max_age,
|
||||
':active' => $active
|
||||
));
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
|
||||
'msg' => array('object_modified', $domain)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
break;
|
||||
case 'resource':
|
||||
if (!is_array($_data['name'])) {
|
||||
$names = array();
|
||||
@@ -4328,6 +4706,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
`address`,
|
||||
`public_comment`,
|
||||
`private_comment`,
|
||||
`internal`,
|
||||
`active`,
|
||||
`sogo_visible`,
|
||||
`created`,
|
||||
@@ -4358,6 +4737,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$aliasdata['goto'] = $row['goto'];
|
||||
$aliasdata['address'] = $row['address'];
|
||||
(!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0;
|
||||
$aliasdata['internal'] = $row['internal'];
|
||||
$aliasdata['active'] = $row['active'];
|
||||
$aliasdata['active_int'] = $row['active'];
|
||||
$aliasdata['sogo_visible'] = $row['sogo_visible'];
|
||||
@@ -4666,6 +5046,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
`mailbox`.`quota`,
|
||||
`mailbox`.`created`,
|
||||
`mailbox`.`modified`,
|
||||
`mailbox`.`authsource`,
|
||||
`quota2`.`bytes`,
|
||||
`attributes`,
|
||||
`custom_attributes`,
|
||||
@@ -4687,6 +5068,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
`mailbox`.`quota`,
|
||||
`mailbox`.`created`,
|
||||
`mailbox`.`modified`,
|
||||
`mailbox`.`authsource`,
|
||||
`quota2replica`.`bytes`,
|
||||
`attributes`,
|
||||
`custom_attributes`,
|
||||
@@ -4716,6 +5098,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100);
|
||||
$mailboxdata['created'] = $row['created'];
|
||||
$mailboxdata['modified'] = $row['modified'];
|
||||
$mailboxdata['authsource'] = ($row['authsource']) ? $row['authsource'] : 'mailcow';
|
||||
|
||||
if ($mailboxdata['percent_in_use'] === '- ') {
|
||||
$mailboxdata['percent_class'] = "info";
|
||||
@@ -4746,7 +5129,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
else if ($SaslLogs['service'] == 'pop3') {
|
||||
$last_pop3_login = strtotime($SaslLogs['datetime']);
|
||||
}
|
||||
else if ($SaslLogs['service'] == 'SSO') {
|
||||
else if ($SaslLogs['service'] == 'SSO') {
|
||||
$last_sso_login = strtotime($SaslLogs['datetime']);
|
||||
}
|
||||
}
|
||||
@@ -4759,7 +5142,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
if (!isset($last_pop3_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
|
||||
$last_pop3_login = 0;
|
||||
}
|
||||
if (!isset($last_sso_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
|
||||
if (!isset($last_sso_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
|
||||
$last_sso_login = 0;
|
||||
}
|
||||
$mailboxdata['last_imap_login'] = $last_imap_login;
|
||||
@@ -4811,7 +5194,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
return $mailboxdata;
|
||||
break;
|
||||
case 'mailbox_templates':
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin" && $_SESSION['access_all_exception'] != "1") {
|
||||
return false;
|
||||
}
|
||||
$_data = (isset($_data)) ? intval($_data) : null;
|
||||
@@ -4847,6 +5230,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
return $rows;
|
||||
}
|
||||
break;
|
||||
case 'mta_sts':
|
||||
$stmt = $pdo->prepare("SELECT * FROM `mta_sts` WHERE `domain` = :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => $_data,
|
||||
));
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (empty($row)){
|
||||
return [];
|
||||
}
|
||||
$row['mx'] = explode(',', $row['mx']);
|
||||
$row['version'] = strtoupper(substr($row['version'], 0, 3)) . substr($row['version'], 3);
|
||||
|
||||
return $row;
|
||||
break;
|
||||
case 'resource_details':
|
||||
$resourcedata = array();
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
|
||||
@@ -5232,6 +5629,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
$stmt->execute(array(
|
||||
':domain' => $domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `mta_sts` WHERE `domain` = :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => $domain,
|
||||
));
|
||||
$stmt = $pdo->query("DELETE FROM `admin` WHERE `superadmin` = 0 AND `username` NOT IN (SELECT `username`FROM `domain_admins`);");
|
||||
$stmt = $pdo->query("DELETE FROM `da_acl` WHERE `username` NOT IN (SELECT `username`FROM `domain_admins`);");
|
||||
try {
|
||||
@@ -5565,7 +5966,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
update_sogo_static_view($username);
|
||||
try {
|
||||
update_sogo_static_view($username);
|
||||
}catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -5779,6 +6188,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
break;
|
||||
}
|
||||
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") {
|
||||
update_sogo_static_view();
|
||||
try {
|
||||
update_sogo_static_view();
|
||||
}catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => $e->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ function quarantine($_action, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt`
|
||||
WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash
|
||||
WHERE `qhash` = :hash
|
||||
AND user_acl.quarantine = 1
|
||||
AND rcpt IN (SELECT username FROM mailbox)');
|
||||
$stmt->execute(array(':hash' => $hash));
|
||||
@@ -65,7 +65,7 @@ function quarantine($_action, $_data = null) {
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt`
|
||||
WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash
|
||||
WHERE `qhash` = :hash
|
||||
AND `user_acl`.`quarantine` = 1
|
||||
AND `username` IN (SELECT `username` FROM `mailbox`)');
|
||||
$stmt->execute(array(':hash' => $hash));
|
||||
@@ -169,7 +169,7 @@ function quarantine($_action, $_data = null) {
|
||||
}
|
||||
}
|
||||
elseif ($release_format == 'raw') {
|
||||
$detail_row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/', 'X-Pre-Release-Spam-Flag $1', $detail_row['msg']);
|
||||
$detail_row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/m', 'X-Pre-Release-Spam-Flag: $1', $detail_row['msg']);
|
||||
$postfix_talk = array(
|
||||
array('220', 'HELO quarantine' . chr(10)),
|
||||
array('250', 'MAIL FROM: ' . $sender . chr(10)),
|
||||
@@ -464,7 +464,7 @@ function quarantine($_action, $_data = null) {
|
||||
}
|
||||
}
|
||||
elseif ($release_format == 'raw') {
|
||||
$row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/', 'X-Pre-Release-Spam-Flag $1', $row['msg']);
|
||||
$row['msg'] = preg_replace('/^X-Spam-Flag: (.*)/m', 'X-Pre-Release-Spam-Flag: $1', $row['msg']);
|
||||
$postfix_talk = array(
|
||||
array('220', 'HELO quarantine' . chr(10)),
|
||||
array('250', 'MAIL FROM: ' . $sender . chr(10)),
|
||||
@@ -833,7 +833,7 @@ function quarantine($_action, $_data = null) {
|
||||
)));
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash');
|
||||
$stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE `qhash` = :hash');
|
||||
$stmt->execute(array(':hash' => $hash));
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
break;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
function ratelimit($_action, $_scope, $_data = null) {
|
||||
function ratelimit($_action, $_scope, $_data = null, $_extra = null) {
|
||||
global $valkey;
|
||||
$_data_log = $_data;
|
||||
switch ($_action) {
|
||||
case 'edit':
|
||||
if (!isset($_SESSION['acl']['ratelimit']) || $_SESSION['acl']['ratelimit'] != "1" ) {
|
||||
if (!hasACLAccess("ratelimit")) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
@@ -93,7 +93,7 @@ function ratelimit($_action, $_scope, $_data = null) {
|
||||
continue;
|
||||
}
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $object)
|
||||
|| ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) {
|
||||
|| ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin' && $_SESSION['access_all_exception'] != '1')) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
|
||||
@@ -30,6 +30,44 @@ if(!file_exists($CSSPath)) {
|
||||
cleanupCSS($hash);
|
||||
}
|
||||
|
||||
$mailcow_apps_processed = $MAILCOW_APPS;
|
||||
$app_links = customize('get', 'app_links');
|
||||
$app_links_processed = $app_links;
|
||||
$hide_mailcow_apps = true;
|
||||
for ($i = 0; $i < count($mailcow_apps_processed); $i++) {
|
||||
if ($hide_mailcow_apps && !$mailcow_apps_processed[$i]['hide']){
|
||||
$hide_mailcow_apps = false;
|
||||
}
|
||||
if (!empty($_SESSION['mailcow_cc_username'])){
|
||||
if ($app_links_processed[$i]['user_link']) {
|
||||
$mailcow_apps_processed[$i]['user_link'] = str_replace('%u', $_SESSION['mailcow_cc_username'], $mailcow_apps_processed[$i]['user_link']);
|
||||
} else {
|
||||
$mailcow_apps_processed[$i]['user_link'] = $mailcow_apps_processed[$i]['link'];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($app_links_processed){
|
||||
for ($i = 0; $i < count($app_links_processed); $i++) {
|
||||
$key = array_key_first($app_links_processed[$i]);
|
||||
if ($hide_mailcow_apps && !$app_links_processed[$i][$key]['hide']){
|
||||
$hide_mailcow_apps = false;
|
||||
}
|
||||
if (!empty($_SESSION['mailcow_cc_username'])){
|
||||
if ($app_links_processed[$i][$key]['user_link']) {
|
||||
$app_links_processed[$i][$key]['user_link'] = str_replace('%u', $_SESSION['mailcow_cc_username'], $app_links_processed[$i][$key]['user_link']);
|
||||
} else {
|
||||
$app_links_processed[$i][$key]['user_link'] = $app_links_processed[$i][$key]['link'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround to get text with <br> straight to twig.
|
||||
// Using "nl2br" doesn't work with Twig as it would escape everything by default.
|
||||
if (isset($UI_TEXTS["ui_footer"])) {
|
||||
$UI_TEXTS["ui_footer"] = nl2br($UI_TEXTS["ui_footer"]);
|
||||
}
|
||||
|
||||
$globalVariables = [
|
||||
'mailcow_hostname' => getenv('MAILCOW_HOSTNAME'),
|
||||
'mailcow_locale' => @$_SESSION['mailcow_locale'],
|
||||
@@ -45,8 +83,11 @@ $globalVariables = [
|
||||
'lang' => $lang,
|
||||
'skip_sogo' => (getenv('SKIP_SOGO') == 'y'),
|
||||
'allow_admin_email_login' => (getenv('ALLOW_ADMIN_EMAIL_LOGIN') == 'n'),
|
||||
'hide_mailcow_apps' => $hide_mailcow_apps,
|
||||
'mailcow_apps' => $MAILCOW_APPS,
|
||||
'app_links' => customize('get', 'app_links'),
|
||||
'mailcow_apps_processed' => $mailcow_apps_processed,
|
||||
'app_links' => $app_links,
|
||||
'app_links_processed' => $app_links_processed,
|
||||
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
|
||||
'uri' => $_SERVER['REQUEST_URI'],
|
||||
];
|
||||
|
||||
@@ -4,7 +4,7 @@ function init_db_schema()
|
||||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "20112024_1105";
|
||||
$db_version = "07102025_1015";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@@ -184,6 +184,7 @@ function init_db_schema()
|
||||
"private_comment" => "TEXT",
|
||||
"public_comment" => "TEXT",
|
||||
"sogo_visible" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"internal" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||
),
|
||||
"keys" => array(
|
||||
@@ -345,10 +346,14 @@ function init_db_schema()
|
||||
"notified" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"user" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'",
|
||||
"qhash" => "VARCHAR(64)",
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("id")
|
||||
),
|
||||
"key" => array(
|
||||
"qhash" => array("qhash")
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
@@ -368,6 +373,7 @@ function init_db_schema()
|
||||
"custom_attributes" => "JSON NOT NULL DEFAULT ('{}')",
|
||||
"kind" => "VARCHAR(100) NOT NULL DEFAULT ''",
|
||||
"multiple_bookings" => "INT NOT NULL DEFAULT -1",
|
||||
"authsource" => "ENUM('mailcow', 'keycloak', 'generic-oidc', 'ldap') DEFAULT 'mailcow'",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
|
||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||
@@ -470,6 +476,23 @@ function init_db_schema()
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"mta_sts" => array(
|
||||
"cols" => array(
|
||||
"id" => "BIGINT NOT NULL",
|
||||
"domain" => "VARCHAR(255) NOT NULL",
|
||||
"version" => "VARCHAR(255) NOT NULL",
|
||||
"mode" => "VARCHAR(255) NOT NULL",
|
||||
"mx" => "VARCHAR(255) NOT NULL",
|
||||
"max_age" => "VARCHAR(255) NOT NULL",
|
||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("domain")
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"user_acl" => array(
|
||||
"cols" => array(
|
||||
"username" => "VARCHAR(255) NOT NULL",
|
||||
@@ -575,6 +598,20 @@ function init_db_schema()
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"identity_provider" => array(
|
||||
"cols" => array(
|
||||
"key" => "VARCHAR(255) NOT NULL",
|
||||
"value" => "TEXT NOT NULL",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("key")
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"logs" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
@@ -1300,6 +1337,14 @@ function init_db_schema()
|
||||
$pdo->query($create);
|
||||
}
|
||||
|
||||
// Clear old app_passwd log entries
|
||||
$pdo->exec("DELETE FROM logs
|
||||
WHERE role != 'unauthenticated'
|
||||
AND JSON_EXTRACT(`call`, '$[0]') = 'app_passwd'
|
||||
AND JSON_EXTRACT(`call`, '$[1]') = 'edit'
|
||||
AND (JSON_CONTAINS_PATH(`call`, 'one', '$[2].password')
|
||||
OR JSON_CONTAINS_PATH(`call`, 'one', '$[2].password2'));");
|
||||
|
||||
// Mitigate imapsync argument injection issue
|
||||
$pdo->query("UPDATE `imapsync` SET `custom_params` = ''
|
||||
WHERE `custom_params` LIKE '%pipemess%'
|
||||
@@ -1455,6 +1500,9 @@ function init_db_schema()
|
||||
));
|
||||
}
|
||||
|
||||
// remove old sogo views and triggers
|
||||
$pdo->query("DROP TRIGGER IF EXISTS sogo_update_password");
|
||||
|
||||
if (php_sapi_name() == "cli") {
|
||||
echo "DB initialization completed" . PHP_EOL;
|
||||
} else {
|
||||
@@ -1464,6 +1512,10 @@ function init_db_schema()
|
||||
'msg' => 'db_init_complete'
|
||||
);
|
||||
}
|
||||
|
||||
// fill quarantine.qhash
|
||||
$pdo->query("UPDATE `quarantine` SET `qhash` = SHA2(CONCAT(`id`, `qid`), 256) WHERE ISNULL(`qhash`)");
|
||||
|
||||
} catch (PDOException $e) {
|
||||
if (php_sapi_name() == "cli") {
|
||||
echo "DB initialization failed: " . print_r($e, true) . PHP_EOL;
|
||||
@@ -1478,6 +1530,7 @@ function init_db_schema()
|
||||
}
|
||||
if (php_sapi_name() == "cli") {
|
||||
include '/web/inc/vars.inc.php';
|
||||
include '/web/inc/functions.inc.php';
|
||||
include '/web/inc/functions.docker.inc.php';
|
||||
// $now = new DateTime();
|
||||
// $mins = $now->getOffset() / 60;
|
||||
@@ -1499,9 +1552,7 @@ if (php_sapi_name() == "cli") {
|
||||
if (intval($res['OK_C']) === 2) {
|
||||
// Be more precise when replacing into _sogo_static_view, col orders may change
|
||||
try {
|
||||
$stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`)
|
||||
SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view");
|
||||
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
|
||||
update_sogo_static_view();
|
||||
echo "Fixed _sogo_static_view" . PHP_EOL;
|
||||
} catch (Exception $e) {
|
||||
// Dunno
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"require": {
|
||||
"robthree/twofactorauth": "^1.6",
|
||||
"yubico/u2flib-server": "^1.0",
|
||||
"phpmailer/phpmailer": "^6.1",
|
||||
"php-mime-mail-parser/php-mime-mail-parser": "^7",
|
||||
"soundasleep/html2text": "^0.5.0",
|
||||
@@ -9,7 +8,9 @@
|
||||
"matthiasmullie/minify": "^1.3",
|
||||
"bshaffer/oauth2-server-php": "^1.11",
|
||||
"mustangostang/spyc": "^0.6.3",
|
||||
"directorytree/ldaprecord": "^2.4",
|
||||
"twig/twig": "^3.0"
|
||||
"directorytree/ldaprecord": "^3.3",
|
||||
"twig/twig": "^3.0",
|
||||
"stevenmaguire/oauth2-keycloak": "^4.0",
|
||||
"league/oauth2-client": "^2.7"
|
||||
}
|
||||
}
|
||||
|
||||
1097
data/web/inc/lib/composer.lock
generated
1097
data/web/inc/lib/composer.lock
generated
File diff suppressed because it is too large
Load Diff
46
data/web/inc/lib/vendor/bin/carbon
vendored
46
data/web/inc/lib/vendor/bin/carbon
vendored
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
@@ -23,18 +24,17 @@ if (PHP_VERSION_ID < 80000) {
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of composer-bin-proxy:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 21);
|
||||
$opened_path = realpath($opened_path) ?: $opened_path;
|
||||
$this->handle = fopen($opened_path, $mode);
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
// remove all traces of this stream wrapper once it has been used
|
||||
stream_wrapper_unregister('composer-bin-proxy');
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,16 @@ if (PHP_VERSION_ID < 80000) {
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
@@ -78,20 +88,32 @@ if (PHP_VERSION_ID < 80000) {
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return fstat($this->handle);
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) {
|
||||
include("composer-bin-proxy://" . __DIR__ . '/..'.'/nesbot/carbon/bin/carbon');
|
||||
exit(0);
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/nesbot/carbon/bin/carbon');
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/nesbot/carbon/bin/carbon';
|
||||
return include __DIR__ . '/..'.'/nesbot/carbon/bin/carbon';
|
||||
|
||||
46
data/web/inc/lib/vendor/bin/var-dump-server
vendored
46
data/web/inc/lib/vendor/bin/var-dump-server
vendored
@@ -12,6 +12,7 @@
|
||||
|
||||
namespace Composer;
|
||||
|
||||
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||
|
||||
if (PHP_VERSION_ID < 80000) {
|
||||
@@ -23,18 +24,17 @@ if (PHP_VERSION_ID < 80000) {
|
||||
{
|
||||
private $handle;
|
||||
private $position;
|
||||
private $realpath;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path)
|
||||
{
|
||||
// get rid of composer-bin-proxy:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 21);
|
||||
$opened_path = realpath($opened_path) ?: $opened_path;
|
||||
$this->handle = fopen($opened_path, $mode);
|
||||
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||
$opened_path = substr($path, 17);
|
||||
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||
$opened_path = $this->realpath;
|
||||
$this->handle = fopen($this->realpath, $mode);
|
||||
$this->position = 0;
|
||||
|
||||
// remove all traces of this stream wrapper once it has been used
|
||||
stream_wrapper_unregister('composer-bin-proxy');
|
||||
|
||||
return (bool) $this->handle;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,16 @@ if (PHP_VERSION_ID < 80000) {
|
||||
return $operation ? flock($this->handle, $operation) : true;
|
||||
}
|
||||
|
||||
public function stream_seek($offset, $whence)
|
||||
{
|
||||
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||
$this->position = ftell($this->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return $this->position;
|
||||
@@ -78,20 +88,32 @@ if (PHP_VERSION_ID < 80000) {
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return fstat($this->handle);
|
||||
return array();
|
||||
}
|
||||
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function url_stat($path, $flags)
|
||||
{
|
||||
$path = substr($path, 17);
|
||||
if (file_exists($path)) {
|
||||
return stat($path);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (function_exists('stream_wrapper_register') && stream_wrapper_register('composer-bin-proxy', 'Composer\BinProxyWrapper')) {
|
||||
include("composer-bin-proxy://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
||||
exit(0);
|
||||
if (
|
||||
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||
) {
|
||||
return include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
||||
}
|
||||
}
|
||||
|
||||
include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server';
|
||||
return include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server';
|
||||
|
||||
21
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/LICENSE
vendored
Normal file
21
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Carbon
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
14
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/README.md
vendored
Normal file
14
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/README.md
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# carbonphp/carbon-doctrine-types
|
||||
|
||||
Types to use Carbon in Doctrine
|
||||
|
||||
## Documentation
|
||||
|
||||
[Check how to use in the official Carbon documentation](https://carbon.nesbot.com/symfony/)
|
||||
|
||||
This package is an externalization of [src/Carbon/Doctrine](https://github.com/briannesbitt/Carbon/tree/2.71.0/src/Carbon/Doctrine)
|
||||
from `nestbot/carbon` package.
|
||||
|
||||
Externalization allows to better deal with different versions of dbal. With
|
||||
version 4.0 of dbal, it no longer sustainable to be compatible with all version
|
||||
using a single code.
|
||||
36
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/composer.json
vendored
Normal file
36
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/composer.json
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "carbonphp/carbon-doctrine-types",
|
||||
"description": "Types to use Carbon in Doctrine",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"date",
|
||||
"time",
|
||||
"DateTime",
|
||||
"Carbon",
|
||||
"Doctrine"
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/dbal": "^4.0.0",
|
||||
"nesbot/carbon": "^2.71.0 || ^3.0.0",
|
||||
"phpunit/phpunit": "^10.3"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/dbal": "<4.0.0 || >=5.0.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Carbon\\Doctrine\\": "src/Carbon/Doctrine/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "KyleKatarn",
|
||||
"email": "kylekatarnls@gmail.com"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "dev"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
interface CarbonDoctrineType
|
||||
{
|
||||
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform);
|
||||
|
||||
public function convertToPHPValue(mixed $value, AbstractPlatform $platform);
|
||||
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
class CarbonImmutableType extends DateTimeImmutableType implements CarbonDoctrineType
|
||||
{
|
||||
}
|
||||
9
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonType.php
vendored
Normal file
9
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/CarbonType.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
class CarbonType extends DateTimeType implements CarbonDoctrineType
|
||||
{
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Carbon package.
|
||||
*
|
||||
* (c) Brian Nesbitt <brian@nesbot.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
@@ -15,7 +8,12 @@ use Carbon\Carbon;
|
||||
use Carbon\CarbonInterface;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\ConversionException;
|
||||
use Doctrine\DBAL\Platforms\DB2Platform;
|
||||
use Doctrine\DBAL\Platforms\OraclePlatform;
|
||||
use Doctrine\DBAL\Platforms\SQLitePlatform;
|
||||
use Doctrine\DBAL\Platforms\SQLServerPlatform;
|
||||
use Doctrine\DBAL\Types\Exception\InvalidType;
|
||||
use Doctrine\DBAL\Types\Exception\ValueNotConvertible;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
@@ -23,6 +21,14 @@ use Exception;
|
||||
*/
|
||||
trait CarbonTypeConverter
|
||||
{
|
||||
/**
|
||||
* This property differentiates types installed by carbonphp/carbon-doctrine-types
|
||||
* from the ones embedded previously in nesbot/carbon source directly.
|
||||
*
|
||||
* @readonly
|
||||
*/
|
||||
public bool $external = true;
|
||||
|
||||
/**
|
||||
* @return class-string<T>
|
||||
*/
|
||||
@@ -31,20 +37,12 @@ trait CarbonTypeConverter
|
||||
return Carbon::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
|
||||
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
|
||||
{
|
||||
$precision = $fieldDeclaration['precision'] ?: 10;
|
||||
|
||||
if ($fieldDeclaration['secondPrecision'] ?? false) {
|
||||
$precision = 0;
|
||||
}
|
||||
|
||||
if ($precision === 10) {
|
||||
$precision = DateTimeDefaultPrecision::get();
|
||||
}
|
||||
$precision = min(
|
||||
$fieldDeclaration['precision'] ?? DateTimeDefaultPrecision::get(),
|
||||
$this->getMaximumPrecision($platform),
|
||||
);
|
||||
|
||||
$type = parent::getSQLDeclaration($fieldDeclaration, $platform);
|
||||
|
||||
@@ -63,10 +61,25 @@ trait CarbonTypeConverter
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*
|
||||
* @return T|null
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform)
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
|
||||
{
|
||||
if ($value === null) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ($value instanceof DateTimeInterface) {
|
||||
return $value->format('Y-m-d H:i:s.u');
|
||||
}
|
||||
|
||||
throw InvalidType::new(
|
||||
$value,
|
||||
static::class,
|
||||
['null', 'DateTime', 'Carbon']
|
||||
);
|
||||
}
|
||||
|
||||
private function doConvertToPHPValue(mixed $value)
|
||||
{
|
||||
$class = $this->getCarbonClassName();
|
||||
|
||||
@@ -88,9 +101,9 @@ trait CarbonTypeConverter
|
||||
}
|
||||
|
||||
if (!$date) {
|
||||
throw ConversionException::conversionFailedFormat(
|
||||
throw ValueNotConvertible::new(
|
||||
$value,
|
||||
$this->getName(),
|
||||
static::class,
|
||||
'Y-m-d H:i:s.u or any format supported by '.$class.'::parse()',
|
||||
$error
|
||||
);
|
||||
@@ -99,25 +112,20 @@ trait CarbonTypeConverter
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||
private function getMaximumPrecision(AbstractPlatform $platform): int
|
||||
{
|
||||
if ($value === null) {
|
||||
return $value;
|
||||
if ($platform instanceof DB2Platform) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
if ($value instanceof DateTimeInterface) {
|
||||
return $value->format('Y-m-d H:i:s.u');
|
||||
if ($platform instanceof OraclePlatform) {
|
||||
return 9;
|
||||
}
|
||||
|
||||
throw ConversionException::conversionFailedInvalidType(
|
||||
$value,
|
||||
$this->getName(),
|
||||
['null', 'DateTime', 'Carbon']
|
||||
);
|
||||
if ($platform instanceof SQLServerPlatform || $platform instanceof SQLitePlatform) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,6 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of the Carbon package.
|
||||
*
|
||||
* (c) Brian Nesbitt <brian@nesbot.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Thanks to https://github.com/flaushi for his suggestion:
|
||||
* https://github.com/doctrine/dbal/issues/2873#issuecomment-534956358
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\VarDateTimeImmutableType;
|
||||
|
||||
class DateTimeImmutableType extends VarDateTimeImmutableType implements CarbonDoctrineType
|
||||
@@ -14,6 +14,14 @@ class DateTimeImmutableType extends VarDateTimeImmutableType implements CarbonDo
|
||||
/** @use CarbonTypeConverter<CarbonImmutable> */
|
||||
use CarbonTypeConverter;
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?CarbonImmutable
|
||||
{
|
||||
return $this->doConvertToPHPValue($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string<CarbonImmutable>
|
||||
*/
|
||||
24
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeType.php
vendored
Normal file
24
data/web/inc/lib/vendor/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine/DateTimeType.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Carbon\Doctrine;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use DateTime;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\VarDateTimeType;
|
||||
|
||||
class DateTimeType extends VarDateTimeType implements CarbonDoctrineType
|
||||
{
|
||||
/** @use CarbonTypeConverter<Carbon> */
|
||||
use CarbonTypeConverter;
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||
*/
|
||||
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?Carbon
|
||||
{
|
||||
return $this->doConvertToPHPValue($value);
|
||||
}
|
||||
}
|
||||
@@ -13,9 +13,4 @@ return array(
|
||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
'u2flib_server\\Error' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\RegisterRequest' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\Registration' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\SignRequest' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\U2F' => $vendorDir . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
);
|
||||
|
||||
@@ -6,8 +6,12 @@ $vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
|
||||
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
|
||||
@@ -15,17 +15,27 @@ return array(
|
||||
'Symfony\\Contracts\\Translation\\' => array($vendorDir . '/symfony/translation-contracts'),
|
||||
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
|
||||
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
|
||||
'Stevenmaguire\\OAuth2\\Client\\' => array($vendorDir . '/stevenmaguire/oauth2-keycloak/src'),
|
||||
'RobThree\\Auth\\' => array($vendorDir . '/robthree/twofactorauth/lib'),
|
||||
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||
'Psr\\Log\\' => array($vendorDir . '/psr/log/src'),
|
||||
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'),
|
||||
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||
'Psr\\Clock\\' => array($vendorDir . '/psr/clock/src'),
|
||||
'PhpMimeMailParser\\' => array($vendorDir . '/php-mime-mail-parser/php-mime-mail-parser/src'),
|
||||
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||
'MatthiasMullie\\PathConverter\\' => array($vendorDir . '/matthiasmullie/path-converter/src'),
|
||||
'MatthiasMullie\\Minify\\' => array($vendorDir . '/matthiasmullie/minify/src'),
|
||||
'League\\OAuth2\\Client\\' => array($vendorDir . '/league/oauth2-client/src'),
|
||||
'LdapRecord\\' => array($vendorDir . '/directorytree/ldaprecord/src'),
|
||||
'Illuminate\\Contracts\\' => array($vendorDir . '/illuminate/contracts'),
|
||||
'Html2Text\\' => array($vendorDir . '/soundasleep/html2text/src'),
|
||||
'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
|
||||
'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
|
||||
'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
|
||||
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
|
||||
'Ddeboer\\Imap\\' => array($vendorDir . '/ddeboer/imap/src'),
|
||||
'Carbon\\Doctrine\\' => array($vendorDir . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine'),
|
||||
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
|
||||
);
|
||||
|
||||
134
data/web/inc/lib/vendor/composer/autoload_static.php
vendored
134
data/web/inc/lib/vendor/composer/autoload_static.php
vendored
@@ -7,8 +7,12 @@ namespace Composer\Autoload;
|
||||
class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
{
|
||||
public static $files = array (
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
|
||||
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
|
||||
'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
|
||||
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
@@ -24,12 +28,12 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'T' =>
|
||||
'T' =>
|
||||
array (
|
||||
'Twig\\' => 5,
|
||||
'Tightenco\\Collect\\' => 18,
|
||||
),
|
||||
'S' =>
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Php81\\' => 23,
|
||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||
@@ -38,141 +42,198 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
'Symfony\\Contracts\\Translation\\' => 30,
|
||||
'Symfony\\Component\\VarDumper\\' => 28,
|
||||
'Symfony\\Component\\Translation\\' => 30,
|
||||
'Stevenmaguire\\OAuth2\\Client\\' => 28,
|
||||
),
|
||||
'R' =>
|
||||
'R' =>
|
||||
array (
|
||||
'RobThree\\Auth\\' => 14,
|
||||
),
|
||||
'P' =>
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\SimpleCache\\' => 16,
|
||||
'Psr\\Log\\' => 8,
|
||||
'Psr\\Http\\Message\\' => 17,
|
||||
'Psr\\Http\\Client\\' => 16,
|
||||
'Psr\\Container\\' => 14,
|
||||
'Psr\\Clock\\' => 10,
|
||||
'PhpMimeMailParser\\' => 18,
|
||||
'PHPMailer\\PHPMailer\\' => 20,
|
||||
),
|
||||
'M' =>
|
||||
'M' =>
|
||||
array (
|
||||
'MatthiasMullie\\PathConverter\\' => 29,
|
||||
'MatthiasMullie\\Minify\\' => 22,
|
||||
),
|
||||
'L' =>
|
||||
'L' =>
|
||||
array (
|
||||
'League\\OAuth2\\Client\\' => 21,
|
||||
'LdapRecord\\' => 11,
|
||||
),
|
||||
'I' =>
|
||||
'I' =>
|
||||
array (
|
||||
'Illuminate\\Contracts\\' => 21,
|
||||
),
|
||||
'H' =>
|
||||
'H' =>
|
||||
array (
|
||||
'Html2Text\\' => 10,
|
||||
),
|
||||
'D' =>
|
||||
'G' =>
|
||||
array (
|
||||
'GuzzleHttp\\Psr7\\' => 16,
|
||||
'GuzzleHttp\\Promise\\' => 19,
|
||||
'GuzzleHttp\\' => 11,
|
||||
),
|
||||
'F' =>
|
||||
array (
|
||||
'Firebase\\JWT\\' => 13,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Ddeboer\\Imap\\' => 13,
|
||||
),
|
||||
'C' =>
|
||||
'C' =>
|
||||
array (
|
||||
'Carbon\\Doctrine\\' => 16,
|
||||
'Carbon\\' => 7,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Twig\\' =>
|
||||
'Twig\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/twig/twig/src',
|
||||
),
|
||||
'Tightenco\\Collect\\' =>
|
||||
'Tightenco\\Collect\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/tightenco/collect/src/Collect',
|
||||
),
|
||||
'Symfony\\Polyfill\\Php81\\' =>
|
||||
'Symfony\\Polyfill\\Php81\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
|
||||
),
|
||||
'Symfony\\Polyfill\\Php80\\' =>
|
||||
'Symfony\\Polyfill\\Php80\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||
),
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||
),
|
||||
'Symfony\\Polyfill\\Ctype\\' =>
|
||||
'Symfony\\Polyfill\\Ctype\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-ctype',
|
||||
),
|
||||
'Symfony\\Contracts\\Translation\\' =>
|
||||
'Symfony\\Contracts\\Translation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/translation-contracts',
|
||||
),
|
||||
'Symfony\\Component\\VarDumper\\' =>
|
||||
'Symfony\\Component\\VarDumper\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/var-dumper',
|
||||
),
|
||||
'Symfony\\Component\\Translation\\' =>
|
||||
'Symfony\\Component\\Translation\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/translation',
|
||||
),
|
||||
'RobThree\\Auth\\' =>
|
||||
'Stevenmaguire\\OAuth2\\Client\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/stevenmaguire/oauth2-keycloak/src',
|
||||
),
|
||||
'RobThree\\Auth\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/robthree/twofactorauth/lib',
|
||||
),
|
||||
'Psr\\SimpleCache\\' =>
|
||||
'Psr\\SimpleCache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
|
||||
),
|
||||
'Psr\\Log\\' =>
|
||||
'Psr\\Log\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/log/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
'Psr\\Http\\Message\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||
1 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||
),
|
||||
'Psr\\Http\\Client\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
||||
),
|
||||
'Psr\\Container\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||
),
|
||||
'PhpMimeMailParser\\' =>
|
||||
'Psr\\Clock\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/clock/src',
|
||||
),
|
||||
'PhpMimeMailParser\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/php-mime-mail-parser/php-mime-mail-parser/src',
|
||||
),
|
||||
'PHPMailer\\PHPMailer\\' =>
|
||||
'PHPMailer\\PHPMailer\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
|
||||
),
|
||||
'MatthiasMullie\\PathConverter\\' =>
|
||||
'MatthiasMullie\\PathConverter\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/matthiasmullie/path-converter/src',
|
||||
),
|
||||
'MatthiasMullie\\Minify\\' =>
|
||||
'MatthiasMullie\\Minify\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/matthiasmullie/minify/src',
|
||||
),
|
||||
'LdapRecord\\' =>
|
||||
'League\\OAuth2\\Client\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/oauth2-client/src',
|
||||
),
|
||||
'LdapRecord\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/directorytree/ldaprecord/src',
|
||||
),
|
||||
'Illuminate\\Contracts\\' =>
|
||||
'Illuminate\\Contracts\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/illuminate/contracts',
|
||||
),
|
||||
'Html2Text\\' =>
|
||||
'Html2Text\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/soundasleep/html2text/src',
|
||||
),
|
||||
'Ddeboer\\Imap\\' =>
|
||||
'GuzzleHttp\\Psr7\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
|
||||
),
|
||||
'GuzzleHttp\\Promise\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
|
||||
),
|
||||
'GuzzleHttp\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
|
||||
),
|
||||
'Firebase\\JWT\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
|
||||
),
|
||||
'Ddeboer\\Imap\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/ddeboer/imap/src',
|
||||
),
|
||||
'Carbon\\' =>
|
||||
'Carbon\\Doctrine\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/carbonphp/carbon-doctrine-types/src/Carbon/Doctrine',
|
||||
),
|
||||
'Carbon\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/nesbot/carbon/src/Carbon',
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixesPsr0 = array (
|
||||
'O' =>
|
||||
'O' =>
|
||||
array (
|
||||
'OAuth2' =>
|
||||
'OAuth2' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/bshaffer/oauth2-server-php/src',
|
||||
),
|
||||
@@ -187,11 +248,6 @@ class ComposerStaticInit873464e4bd965a3168f133248b1b218b
|
||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
'u2flib_server\\Error' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\RegisterRequest' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\Registration' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\SignRequest' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
'u2flib_server\\U2F' => __DIR__ . '/..' . '/yubico/u2flib-server/src/u2flib_server/U2F.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
||||
1152
data/web/inc/lib/vendor/composer/installed.json
vendored
1152
data/web/inc/lib/vendor/composer/installed.json
vendored
File diff suppressed because it is too large
Load Diff
195
data/web/inc/lib/vendor/composer/installed.php
vendored
195
data/web/inc/lib/vendor/composer/installed.php
vendored
@@ -28,6 +28,15 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'carbonphp/carbon-doctrine-types' => array(
|
||||
'pretty_version' => '3.2.0',
|
||||
'version' => '3.2.0.0',
|
||||
'reference' => '18ba5ddfec8976260ead6e866180bd5d2f71aa1d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../carbonphp/carbon-doctrine-types',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ddeboer/imap' => array(
|
||||
'pretty_version' => '1.13.1',
|
||||
'version' => '1.13.1.0',
|
||||
@@ -38,9 +47,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'directorytree/ldaprecord' => array(
|
||||
'pretty_version' => 'v2.10.1',
|
||||
'version' => '2.10.1.0',
|
||||
'reference' => 'bf512d9af7a7b0e2ed7a666ab29cefdd027bee88',
|
||||
'pretty_version' => 'v2.20.5',
|
||||
'version' => '2.20.5.0',
|
||||
'reference' => '5bd0a5a9d257cf1049ae83055dbba4c3479ddf16',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../directorytree/ldaprecord',
|
||||
'aliases' => array(),
|
||||
@@ -52,15 +61,60 @@
|
||||
0 => '*',
|
||||
),
|
||||
),
|
||||
'firebase/php-jwt' => array(
|
||||
'pretty_version' => 'v6.5.0',
|
||||
'version' => '6.5.0.0',
|
||||
'reference' => 'e94e7353302b0c11ec3cfff7180cd0b1743975d2',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../firebase/php-jwt',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/guzzle' => array(
|
||||
'pretty_version' => '7.5.0',
|
||||
'version' => '7.5.0.0',
|
||||
'reference' => 'b50a2a1251152e43f6a37f0fa053e730a67d25ba',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/promises' => array(
|
||||
'pretty_version' => '1.5.2',
|
||||
'version' => '1.5.2.0',
|
||||
'reference' => 'b94b2807d85443f9719887892882d0329d1e2598',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/promises',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'guzzlehttp/psr7' => array(
|
||||
'pretty_version' => '2.4.5',
|
||||
'version' => '2.4.5.0',
|
||||
'reference' => '0454e12ef0cd597ccd2adb036f7bda4e7fface66',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../guzzlehttp/psr7',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'illuminate/contracts' => array(
|
||||
'pretty_version' => 'v9.3.0',
|
||||
'version' => '9.3.0.0',
|
||||
'reference' => 'bf4b3c254c49d28157645d01e4883b5951b1e1d0',
|
||||
'pretty_version' => 'v10.44.0',
|
||||
'version' => '10.44.0.0',
|
||||
'reference' => '8d7152c4a1f5d9cf7da3e8b71f23e4556f6138ac',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../illuminate/contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/oauth2-client' => array(
|
||||
'pretty_version' => '2.7.0',
|
||||
'version' => '2.7.0.0',
|
||||
'reference' => '160d6274b03562ebeb55ed18399281d8118b76c8',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/oauth2-client',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'matthiasmullie/minify' => array(
|
||||
'pretty_version' => '1.3.66',
|
||||
'version' => '1.3.66.0',
|
||||
@@ -95,9 +149,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'nesbot/carbon' => array(
|
||||
'pretty_version' => '2.57.0',
|
||||
'version' => '2.57.0.0',
|
||||
'reference' => '4a54375c21eea4811dbd1149fe6b246517554e78',
|
||||
'pretty_version' => '2.72.3',
|
||||
'version' => '2.72.3.0',
|
||||
'reference' => '0c6fd108360c562f6e4fd1dedb8233b423e91c83',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nesbot/carbon',
|
||||
'aliases' => array(),
|
||||
@@ -130,6 +184,21 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'e41a24703d4560fd0acb709162f73b8adfc3aa0d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/clock',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/clock-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/container' => array(
|
||||
'pretty_version' => '2.0.2',
|
||||
'version' => '2.0.2.0',
|
||||
@@ -139,6 +208,51 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => '2dfb5f6c5eff0e91e20e913f8c5452ed95b86621',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-client',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-client-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-factory' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-factory-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/http-message' => array(
|
||||
'pretty_version' => '1.0.1',
|
||||
'version' => '1.0.1.0',
|
||||
'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/http-message',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/http-message-implementation' => array(
|
||||
'dev_requirement' => false,
|
||||
'provided' => array(
|
||||
0 => '1.0',
|
||||
),
|
||||
),
|
||||
'psr/log' => array(
|
||||
'pretty_version' => '3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
@@ -157,6 +271,15 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'ralouphie/getallheaders' => array(
|
||||
'pretty_version' => '3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
'reference' => '120b605dfeb996808c31b6477290a714d356e822',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../ralouphie/getallheaders',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'robthree/twofactorauth' => array(
|
||||
'pretty_version' => '1.8.1',
|
||||
'version' => '1.8.1.0',
|
||||
@@ -175,6 +298,15 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'stevenmaguire/oauth2-keycloak' => array(
|
||||
'pretty_version' => '4.0.0',
|
||||
'version' => '4.0.0.0',
|
||||
'reference' => '05ead6bb6bcd2b6f96dfae87c769dcd3e5f6129d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../stevenmaguire/oauth2-keycloak',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => 'v3.5.0',
|
||||
'version' => '3.5.0.0',
|
||||
@@ -194,18 +326,18 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-mbstring' => array(
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'reference' => '0abb51d2f102e00a4eefcf46ba7fec406d245825',
|
||||
'pretty_version' => 'v1.29.0',
|
||||
'version' => '1.29.0.0',
|
||||
'reference' => '9773676c8a1bb1f8d4340a62efe641cf76eda7ec',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.24.0',
|
||||
'version' => '1.24.0.0',
|
||||
'reference' => '57b712b08eddb97c762a8caa32c84e037892d2e9',
|
||||
'pretty_version' => 'v1.29.0',
|
||||
'version' => '1.29.0.0',
|
||||
'reference' => '87b68208d5c1188808dd7839ee1e6c8ec3b02f1b',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
@@ -221,18 +353,18 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation' => array(
|
||||
'pretty_version' => 'v6.0.5',
|
||||
'version' => '6.0.5.0',
|
||||
'reference' => 'e69501c71107cc3146b32aaa45f4edd0c3427875',
|
||||
'pretty_version' => 'v6.4.3',
|
||||
'version' => '6.4.3.0',
|
||||
'reference' => '637c51191b6b184184bbf98937702bcf554f7d04',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/translation',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/translation-contracts' => array(
|
||||
'pretty_version' => 'v3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
'reference' => '1b6ea5a7442af5a12dba3dbd6d71034b5b234e77',
|
||||
'pretty_version' => 'v3.4.1',
|
||||
'version' => '3.4.1.0',
|
||||
'reference' => '06450585bf65e978026bda220cdebca3f867fde7',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/translation-contracts',
|
||||
'aliases' => array(),
|
||||
@@ -245,18 +377,18 @@
|
||||
),
|
||||
),
|
||||
'symfony/var-dumper' => array(
|
||||
'pretty_version' => 'v6.0.5',
|
||||
'version' => '6.0.5.0',
|
||||
'reference' => '60d6a756d5f485df5e6e40b337334848f79f61ce',
|
||||
'pretty_version' => 'v6.4.3',
|
||||
'version' => '6.4.3.0',
|
||||
'reference' => '0435a08f69125535336177c29d56af3abc1f69da',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'tightenco/collect' => array(
|
||||
'pretty_version' => 'v8.83.2',
|
||||
'version' => '8.83.2.0',
|
||||
'reference' => 'd9c66d586ec2d216d8a31283d73f8df1400cc722',
|
||||
'pretty_version' => 'v9.52.7',
|
||||
'version' => '9.52.7.0',
|
||||
'reference' => 'b15143cd11fe01a700fcc449df61adc64452fa6d',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../tightenco/collect',
|
||||
'aliases' => array(),
|
||||
@@ -271,14 +403,5 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'yubico/u2flib-server' => array(
|
||||
'pretty_version' => '1.0.2',
|
||||
'version' => '1.0.2.0',
|
||||
'reference' => '55d813acf68212ad2cadecde07551600d6971939',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../yubico/u2flib-server',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -7,7 +7,10 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Please update the below information with your environment. -->
|
||||
<!--
|
||||
Please update the below information with your environment.
|
||||
Issues filed without the below information will be closed.
|
||||
-->
|
||||
**Environment:**
|
||||
- LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
|
||||
- PHP Version: [e.g. 7.3 / 7.4 / 8.0]
|
||||
|
||||
@@ -11,7 +11,10 @@ assignees: ''
|
||||
<!-- https://github.com/sponsors/stevebauman -->
|
||||
<!-- Thank you for your understanding. -->
|
||||
|
||||
<!-- Please update the below information with your environment. -->
|
||||
<!--
|
||||
Please update the below information with your environment.
|
||||
Issues filed without the below information will be closed.
|
||||
-->
|
||||
**Environment:**
|
||||
- LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
|
||||
- PHP Version: [e.g. 7.3 / 7.4 / 8.0]
|
||||
|
||||
62
data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-integration-tests.yml
vendored
Normal file
62
data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-integration-tests.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: run-integration-tests
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
run-tests:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
services:
|
||||
ldap:
|
||||
image: osixia/openldap:1.4.0
|
||||
env:
|
||||
LDAP_TLS_VERIFY_CLIENT: try
|
||||
LDAP_OPENLDAP_UID: 1000
|
||||
LDAP_OPENLDAP_GID: 1000
|
||||
LDAP_ORGANISATION: Local
|
||||
LDAP_DOMAIN: local.com
|
||||
LDAP_ADMIN_PASSWORD: secret
|
||||
ports:
|
||||
- 389:389
|
||||
- 636:636
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
php: [8.1, 8.0, 7.4]
|
||||
|
||||
name: ${{ matrix.os }} - P${{ matrix.php }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/files
|
||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||
|
||||
- name: Set ldap.conf file permissions
|
||||
run: sudo chown -R $USER:$USER /etc/ldap/ldap.conf
|
||||
|
||||
- name: Create ldap.conf file disabling TLS verification
|
||||
run: sudo echo "TLS_REQCERT never" > "/etc/ldap/ldap.conf"
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: ldap, json
|
||||
coverage: none
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer update --prefer-dist --no-interaction
|
||||
|
||||
- name: Execute tests
|
||||
run: vendor/bin/phpunit --testsuite Integration
|
||||
@@ -9,20 +9,20 @@ on:
|
||||
jobs:
|
||||
run-tests:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.os }} - P${{ matrix.php }}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
php: [8.1, 8.0, 7.4, 7.3]
|
||||
|
||||
name: ${{ matrix.os }} - P${{ matrix.php }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.composer/cache/files
|
||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||
@@ -38,41 +38,4 @@ jobs:
|
||||
run: composer update --prefer-dist --no-interaction
|
||||
|
||||
- name: Execute tests
|
||||
run: vendor/bin/phpunit
|
||||
|
||||
run-analysis:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Static code analysis (PHP ${{ matrix.php }})
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
php: [8.0]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache dependencies
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.composer/cache/files
|
||||
key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: ldap, json
|
||||
coverage: none
|
||||
tools: psalm
|
||||
|
||||
- name: Validate composer.json
|
||||
run: composer validate
|
||||
|
||||
- name: Install dependencies
|
||||
run: composer update --prefer-dist --no-interaction
|
||||
|
||||
- name: Run Psalm
|
||||
run: psalm
|
||||
run: vendor/bin/phpunit --testsuite Unit
|
||||
|
||||
@@ -1,8 +1 @@
|
||||
preset: laravel
|
||||
enabled:
|
||||
- phpdoc_align
|
||||
- phpdoc_separation
|
||||
- unalign_double_arrow
|
||||
disabled:
|
||||
- laravel_phpdoc_alignment
|
||||
- laravel_phpdoc_separation
|
||||
|
||||
@@ -32,11 +32,12 @@
|
||||
"php": ">=7.3",
|
||||
"ext-ldap": "*",
|
||||
"ext-json": "*",
|
||||
"psr/log": "*",
|
||||
"psr/log": "^1.0|^2.0|^3.0",
|
||||
"psr/simple-cache": "^1.0|^2.0",
|
||||
"nesbot/carbon": "^1.0|^2.0",
|
||||
"tightenco/collect": "^5.6|^6.0|^7.0|^8.0",
|
||||
"illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0"
|
||||
"tightenco/collect": "^5.6|^6.0|^7.0|^8.0|^9.0",
|
||||
"illuminate/contracts": "^5.0|^6.0|^7.0|^8.0|^9.0|^10.0",
|
||||
"symfony/polyfill-php80": "^1.25"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
|
||||
35
data/web/inc/lib/vendor/directorytree/ldaprecord/docker-compose.yml
vendored
Normal file
35
data/web/inc/lib/vendor/directorytree/ldaprecord/docker-compose.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
ldap:
|
||||
image: osixia/openldap:1.4.0
|
||||
container_name: ldap
|
||||
restart: always
|
||||
hostname: local.com
|
||||
environment:
|
||||
LDAP_TLS_VERIFY_CLIENT: try
|
||||
LDAP_OPENLDAP_UID: 1000
|
||||
LDAP_OPENLDAP_GID: 1000
|
||||
LDAP_ORGANISATION: Local
|
||||
LDAP_DOMAIN : local.com
|
||||
LDAP_ADMIN_PASSWORD: secret
|
||||
ports:
|
||||
- "389:389"
|
||||
- "636:636"
|
||||
networks:
|
||||
- local
|
||||
|
||||
ldapadmin:
|
||||
image: osixia/phpldapadmin:0.9.0
|
||||
container_name: ldapadmin
|
||||
environment:
|
||||
PHPLDAPADMIN_LDAP_HOSTS: ldap
|
||||
restart: always
|
||||
ports:
|
||||
- "6443:443"
|
||||
networks:
|
||||
- local
|
||||
|
||||
networks:
|
||||
local:
|
||||
driver: bridge
|
||||
@@ -10,8 +10,11 @@
|
||||
stopOnFailure="false"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="LdapRecord Test Suite">
|
||||
<directory suffix="Test.php">./tests/</directory>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Integration">
|
||||
<directory suffix="Test.php">./tests/Integration</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="7"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<directory name="vendor" />
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
</psalm>
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/DirectoryTree/LdapRecord/actions">
|
||||
<img src="https://img.shields.io/github/workflow/status/directorytree/ldaprecord/run-tests.svg?style=flat-square">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/directorytree/ldaprecord/run-tests.yml?branch=master&style=flat-square">
|
||||
</a>
|
||||
<a href="https://scrutinizer-ci.com/g/DirectoryTree/LdapRecord/?branch=master">
|
||||
<img src="https://img.shields.io/scrutinizer/g/DirectoryTree/LdapRecord/master.svg?style=flat-square"/>
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
⏲ **Up and Running Fast**
|
||||
|
||||
Connect to your LDAP servers and start running queries at lightning speed.
|
||||
Connect to your LDAP servers and start running queries in a matter of minutes.
|
||||
|
||||
💡 **Fluent Filter Builder**
|
||||
|
||||
|
||||
@@ -30,9 +30,9 @@ abstract class Event
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param LdapInterface $connection
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param LdapInterface $connection
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*/
|
||||
public function __construct(LdapInterface $connection, $username, $password)
|
||||
{
|
||||
|
||||
@@ -38,8 +38,8 @@ class Guard
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param LdapInterface $connection
|
||||
* @param DomainConfiguration $configuration
|
||||
* @param LdapInterface $connection
|
||||
* @param DomainConfiguration $configuration
|
||||
*/
|
||||
public function __construct(LdapInterface $connection, DomainConfiguration $configuration)
|
||||
{
|
||||
@@ -50,10 +50,9 @@ class Guard
|
||||
/**
|
||||
* Attempt binding a user to the LDAP server.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param bool $stayBound
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @param bool $stayBound
|
||||
* @return bool
|
||||
*
|
||||
* @throws UsernameRequiredException
|
||||
@@ -90,8 +89,8 @@ class Guard
|
||||
/**
|
||||
* Attempt binding a user to the LDAP server. Supports anonymous binding.
|
||||
*
|
||||
* @param string|null $username
|
||||
* @param string|null $password
|
||||
* @param string|null $username
|
||||
* @param string|null $password
|
||||
*
|
||||
* @throws BindException
|
||||
* @throws \LdapRecord\ConnectionException
|
||||
@@ -148,8 +147,7 @@ class Guard
|
||||
/**
|
||||
* Set the event dispatcher instance.
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function setDispatcher(DispatcherInterface $dispatcher)
|
||||
@@ -160,9 +158,8 @@ class Guard
|
||||
/**
|
||||
* Fire the attempting event.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return void
|
||||
*/
|
||||
protected function fireAttemptingEvent($username, $password)
|
||||
@@ -175,9 +172,8 @@ class Guard
|
||||
/**
|
||||
* Fire the passed event.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return void
|
||||
*/
|
||||
protected function firePassedEvent($username, $password)
|
||||
@@ -190,9 +186,8 @@ class Guard
|
||||
/**
|
||||
* Fire the failed event.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return void
|
||||
*/
|
||||
protected function fireFailedEvent($username, $password)
|
||||
@@ -205,9 +200,8 @@ class Guard
|
||||
/**
|
||||
* Fire the binding event.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return void
|
||||
*/
|
||||
protected function fireBindingEvent($username, $password)
|
||||
@@ -220,9 +214,8 @@ class Guard
|
||||
/**
|
||||
* Fire the bound event.
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return void
|
||||
*/
|
||||
protected function fireBoundEvent($username, $password)
|
||||
|
||||
@@ -58,7 +58,7 @@ class DomainConfiguration
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
*
|
||||
* @throws ConfigurationException When an option value given is an invalid type.
|
||||
*/
|
||||
@@ -74,9 +74,8 @@ class DomainConfiguration
|
||||
/**
|
||||
* Extend the configuration with a custom option, or override an existing.
|
||||
*
|
||||
* @param string $option
|
||||
* @param mixed $default
|
||||
*
|
||||
* @param string $option
|
||||
* @param mixed $default
|
||||
* @return void
|
||||
*/
|
||||
public static function extend($option, $default = null)
|
||||
@@ -107,8 +106,8 @@ class DomainConfiguration
|
||||
/**
|
||||
* Set a configuration option.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws ConfigurationException When an option value given is an invalid type.
|
||||
*/
|
||||
@@ -122,8 +121,7 @@ class DomainConfiguration
|
||||
/**
|
||||
* Returns the value for the specified configuration options.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*
|
||||
* @throws ConfigurationException When the option specified does not exist.
|
||||
@@ -140,8 +138,7 @@ class DomainConfiguration
|
||||
/**
|
||||
* Checks if a configuration option exists.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function has($key)
|
||||
@@ -152,9 +149,8 @@ class DomainConfiguration
|
||||
/**
|
||||
* Validate the configuration option.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*
|
||||
* @throws ConfigurationException When an option value given is an invalid type.
|
||||
|
||||
@@ -30,8 +30,8 @@ abstract class Validator
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __construct($key, $value)
|
||||
{
|
||||
|
||||
@@ -88,8 +88,8 @@ class Connection
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config
|
||||
* @param LdapInterface|null $ldap
|
||||
* @param array|DomainConfiguration $config
|
||||
* @param LdapInterface|null $ldap
|
||||
*/
|
||||
public function __construct($config = [], LdapInterface $ldap = null)
|
||||
{
|
||||
@@ -109,15 +109,18 @@ class Connection
|
||||
/**
|
||||
* Set the connection configuration.
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @param array|DomainConfiguration $config
|
||||
* @return $this
|
||||
*
|
||||
* @throws Configuration\ConfigurationException
|
||||
*/
|
||||
public function setConfiguration($config = [])
|
||||
{
|
||||
$this->configuration = new DomainConfiguration($config);
|
||||
if (! $config instanceof DomainConfiguration) {
|
||||
$config = new DomainConfiguration($config);
|
||||
}
|
||||
|
||||
$this->configuration = $config;
|
||||
|
||||
$this->hosts = $this->configuration->get('hosts');
|
||||
|
||||
@@ -129,8 +132,7 @@ class Connection
|
||||
/**
|
||||
* Set the LDAP connection.
|
||||
*
|
||||
* @param LdapInterface $ldap
|
||||
*
|
||||
* @param LdapInterface $ldap
|
||||
* @return $this
|
||||
*/
|
||||
public function setLdapConnection(LdapInterface $ldap)
|
||||
@@ -143,8 +145,7 @@ class Connection
|
||||
/**
|
||||
* Set the event dispatcher.
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
* @return $this
|
||||
*/
|
||||
public function setDispatcher(DispatcherInterface $dispatcher)
|
||||
@@ -192,8 +193,7 @@ class Connection
|
||||
/**
|
||||
* Set the cache store.
|
||||
*
|
||||
* @param CacheInterface $store
|
||||
*
|
||||
* @param CacheInterface $store
|
||||
* @return $this
|
||||
*/
|
||||
public function setCache(CacheInterface $store)
|
||||
@@ -238,9 +238,8 @@ class Connection
|
||||
*
|
||||
* If no username or password is specified, then the configured credentials are used.
|
||||
*
|
||||
* @param string|null $username
|
||||
* @param string|null $password
|
||||
*
|
||||
* @param string|null $username
|
||||
* @param string|null $password
|
||||
* @return Connection
|
||||
*
|
||||
* @throws Auth\BindException
|
||||
@@ -298,6 +297,16 @@ class Connection
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone the connection.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function replicate()
|
||||
{
|
||||
return new static($this->configuration, new $this->ldap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect from the LDAP server.
|
||||
*
|
||||
@@ -311,8 +320,7 @@ class Connection
|
||||
/**
|
||||
* Dispatch an event.
|
||||
*
|
||||
* @param object $event
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
*/
|
||||
public function dispatch($event)
|
||||
@@ -335,8 +343,7 @@ class Connection
|
||||
/**
|
||||
* Perform the operation on the LDAP connection.
|
||||
*
|
||||
* @param Closure $operation
|
||||
*
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*/
|
||||
public function run(Closure $operation)
|
||||
@@ -359,11 +366,27 @@ class Connection
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the operation on an isolated LDAP connection.
|
||||
*
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*/
|
||||
public function isolate(Closure $operation)
|
||||
{
|
||||
$connection = $this->replicate();
|
||||
|
||||
try {
|
||||
return $operation($connection);
|
||||
} finally {
|
||||
$connection->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to get an exception for the cause of failure.
|
||||
*
|
||||
* @param LdapRecordException $e
|
||||
*
|
||||
* @param LdapRecordException $e
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getExceptionForCauseOfFailure(LdapRecordException $e)
|
||||
@@ -383,8 +406,7 @@ class Connection
|
||||
/**
|
||||
* Run the operation callback on the current LDAP connection.
|
||||
*
|
||||
* @param Closure $operation
|
||||
*
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -439,9 +461,8 @@ class Connection
|
||||
/**
|
||||
* Attempt to retry an LDAP operation if due to a lost connection.
|
||||
*
|
||||
* @param LdapRecordException $e
|
||||
* @param Closure $operation
|
||||
*
|
||||
* @param LdapRecordException $e
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -461,8 +482,7 @@ class Connection
|
||||
/**
|
||||
* Retry the operation on the current host.
|
||||
*
|
||||
* @param Closure $operation
|
||||
*
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -483,9 +503,8 @@ class Connection
|
||||
/**
|
||||
* Attempt the operation again on the next host.
|
||||
*
|
||||
* @param LdapRecordException $e
|
||||
* @param Closure $operation
|
||||
*
|
||||
* @param LdapRecordException $e
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
|
||||
@@ -81,9 +81,8 @@ class ConnectionManager
|
||||
/**
|
||||
* Forward missing method calls onto the instance.
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $args
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
@@ -104,9 +103,8 @@ class ConnectionManager
|
||||
/**
|
||||
* Add a new connection.
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @param string|null $name
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @param string|null $name
|
||||
* @return $this
|
||||
*/
|
||||
public function add(Connection $connection, $name = null)
|
||||
@@ -123,8 +121,7 @@ class ConnectionManager
|
||||
/**
|
||||
* Remove a connection.
|
||||
*
|
||||
* @param $name
|
||||
*
|
||||
* @param $name
|
||||
* @return $this
|
||||
*/
|
||||
public function remove($name)
|
||||
@@ -147,8 +144,7 @@ class ConnectionManager
|
||||
/**
|
||||
* Get a connection by name or return the default.
|
||||
*
|
||||
* @param string|null $name
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return Connection
|
||||
*
|
||||
* @throws ContainerException If the given connection does not exist.
|
||||
@@ -185,8 +181,7 @@ class ConnectionManager
|
||||
/**
|
||||
* Checks if the connection exists.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($name)
|
||||
@@ -197,8 +192,7 @@ class ConnectionManager
|
||||
/**
|
||||
* Set the default connection name.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefault($name = null)
|
||||
@@ -237,8 +231,7 @@ class ConnectionManager
|
||||
/**
|
||||
* Set the event logger to use.
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
* @return void
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger)
|
||||
@@ -299,8 +292,7 @@ class ConnectionManager
|
||||
/**
|
||||
* Set the event dispatcher.
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
* @return void
|
||||
*/
|
||||
public function setDispatcher(DispatcherInterface $dispatcher)
|
||||
|
||||
@@ -48,9 +48,8 @@ class Container
|
||||
/**
|
||||
* Forward missing static calls onto the current instance.
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $args
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $args
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($method, $args)
|
||||
@@ -71,8 +70,7 @@ class Container
|
||||
/**
|
||||
* Set the container instance.
|
||||
*
|
||||
* @param Container|null $container
|
||||
*
|
||||
* @param Container|null $container
|
||||
* @return Container|null
|
||||
*/
|
||||
public static function setInstance(self $container = null)
|
||||
@@ -103,9 +101,8 @@ class Container
|
||||
/**
|
||||
* Forward missing method calls onto the connection manager.
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $args
|
||||
*
|
||||
* @param string $method
|
||||
* @param mixed $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
|
||||
@@ -28,9 +28,9 @@ class DetailedError
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $errorCode
|
||||
* @param string $errorMessage
|
||||
* @param string $diagnosticMessage
|
||||
* @param int $errorCode
|
||||
* @param string $errorMessage
|
||||
* @param string $diagnosticMessage
|
||||
*/
|
||||
public function __construct($errorCode, $errorMessage, $diagnosticMessage)
|
||||
{
|
||||
|
||||
@@ -7,8 +7,7 @@ trait DetectsErrors
|
||||
/**
|
||||
* Determine if the error was caused by a lost connection.
|
||||
*
|
||||
* @param string $error
|
||||
*
|
||||
* @param string $error
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByLostConnection($error)
|
||||
@@ -19,8 +18,7 @@ trait DetectsErrors
|
||||
/**
|
||||
* Determine if the error was caused by lack of pagination support.
|
||||
*
|
||||
* @param string $error
|
||||
*
|
||||
* @param string $error
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByPaginationSupport($error)
|
||||
@@ -31,8 +29,7 @@ trait DetectsErrors
|
||||
/**
|
||||
* Determine if the error was caused by a size limit warning.
|
||||
*
|
||||
* @param $error
|
||||
*
|
||||
* @param $error
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedBySizeLimit($error)
|
||||
@@ -43,8 +40,7 @@ trait DetectsErrors
|
||||
/**
|
||||
* Determine if the error was caused by a "No such object" warning.
|
||||
*
|
||||
* @param string $error
|
||||
*
|
||||
* @param string $error
|
||||
* @return bool
|
||||
*/
|
||||
protected function causedByNoSuchObject($error)
|
||||
@@ -55,15 +51,14 @@ trait DetectsErrors
|
||||
/**
|
||||
* Determine if the error contains the any of the messages.
|
||||
*
|
||||
* @param string $error
|
||||
* @param string|array $messages
|
||||
*
|
||||
* @param string $error
|
||||
* @param string|array $messages
|
||||
* @return bool
|
||||
*/
|
||||
protected function errorContainsMessage($error, $messages = [])
|
||||
{
|
||||
foreach ((array) $messages as $message) {
|
||||
if (strpos($error, $message) !== false) {
|
||||
if (str_contains((string) $error, $message)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,9 @@ trait EscapesValues
|
||||
/**
|
||||
* Prepare a value to be escaped.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
* @return EscapedValue
|
||||
*/
|
||||
public function escape($value, $ignore = '', $flags = 0)
|
||||
|
||||
@@ -16,7 +16,7 @@ abstract class ConnectionEvent
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @param Connection $connection
|
||||
*/
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
|
||||
@@ -46,7 +46,7 @@ class Dispatcher implements DispatcherInterface
|
||||
public function listen($events, $listener)
|
||||
{
|
||||
foreach ((array) $events as $event) {
|
||||
if (strpos($event, '*') !== false) {
|
||||
if (str_contains((string) $event, '*')) {
|
||||
$this->setupWildcardListen($event, $listener);
|
||||
} else {
|
||||
$this->listeners[$event][] = $this->makeListener($listener);
|
||||
@@ -57,9 +57,8 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Setup a wildcard listener callback.
|
||||
*
|
||||
* @param string $event
|
||||
* @param mixed $listener
|
||||
*
|
||||
* @param string $event
|
||||
* @param mixed $listener
|
||||
* @return void
|
||||
*/
|
||||
protected function setupWildcardListen($event, $listener)
|
||||
@@ -134,9 +133,8 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Parse the given event and payload and prepare them for dispatching.
|
||||
*
|
||||
* @param mixed $event
|
||||
* @param mixed $payload
|
||||
*
|
||||
* @param mixed $event
|
||||
* @param mixed $payload
|
||||
* @return array
|
||||
*/
|
||||
protected function parseEventAndPayload($event, $payload)
|
||||
@@ -168,8 +166,7 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Get the wildcard listeners for the event.
|
||||
*
|
||||
* @param string $eventName
|
||||
*
|
||||
* @param string $eventName
|
||||
* @return array
|
||||
*/
|
||||
protected function getWildcardListeners($eventName)
|
||||
@@ -190,9 +187,8 @@ class Dispatcher implements DispatcherInterface
|
||||
*
|
||||
* This function is a direct excerpt from Laravel's Str::is().
|
||||
*
|
||||
* @param string $wildcard
|
||||
* @param string $eventName
|
||||
*
|
||||
* @param string $wildcard
|
||||
* @param string $eventName
|
||||
* @return bool
|
||||
*/
|
||||
protected function wildcardContainsEvent($wildcard, $eventName)
|
||||
@@ -229,9 +225,8 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Add the listeners for the event's interfaces to the given array.
|
||||
*
|
||||
* @param string $eventName
|
||||
* @param array $listeners
|
||||
*
|
||||
* @param string $eventName
|
||||
* @param array $listeners
|
||||
* @return array
|
||||
*/
|
||||
protected function addInterfaceListeners($eventName, array $listeners = [])
|
||||
@@ -250,9 +245,8 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Register an event listener with the dispatcher.
|
||||
*
|
||||
* @param \Closure|string $listener
|
||||
* @param bool $wildcard
|
||||
*
|
||||
* @param \Closure|string $listener
|
||||
* @param bool $wildcard
|
||||
* @return \Closure
|
||||
*/
|
||||
public function makeListener($listener, $wildcard = false)
|
||||
@@ -273,9 +267,8 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Create a class based listener.
|
||||
*
|
||||
* @param string $listener
|
||||
* @param bool $wildcard
|
||||
*
|
||||
* @param string $listener
|
||||
* @param bool $wildcard
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function createClassListener($listener, $wildcard = false)
|
||||
@@ -295,8 +288,7 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Create the class based event callable.
|
||||
*
|
||||
* @param string $listener
|
||||
*
|
||||
* @param string $listener
|
||||
* @return callable
|
||||
*/
|
||||
protected function createClassCallable($listener)
|
||||
@@ -309,13 +301,12 @@ class Dispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Parse the class listener into class and method.
|
||||
*
|
||||
* @param string $listener
|
||||
*
|
||||
* @param string $listener
|
||||
* @return array
|
||||
*/
|
||||
protected function parseListenerCallback($listener)
|
||||
{
|
||||
return strpos($listener, '@') !== false
|
||||
return str_contains((string) $listener, '@')
|
||||
? explode('@', $listener, 2)
|
||||
: [$listener, 'handle'];
|
||||
}
|
||||
@@ -325,7 +316,7 @@ class Dispatcher implements DispatcherInterface
|
||||
*/
|
||||
public function forget($event)
|
||||
{
|
||||
if (strpos($event, '*') !== false) {
|
||||
if (str_contains((string) $event, '*')) {
|
||||
unset($this->wildcards[$event]);
|
||||
} else {
|
||||
unset($this->listeners[$event]);
|
||||
|
||||
@@ -7,9 +7,8 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Register an event listener with the dispatcher.
|
||||
*
|
||||
* @param string|array $events
|
||||
* @param mixed $listener
|
||||
*
|
||||
* @param string|array $events
|
||||
* @param mixed $listener
|
||||
* @return void
|
||||
*/
|
||||
public function listen($events, $listener);
|
||||
@@ -17,8 +16,7 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Determine if a given event has listeners.
|
||||
*
|
||||
* @param string $eventName
|
||||
*
|
||||
* @param string $eventName
|
||||
* @return bool
|
||||
*/
|
||||
public function hasListeners($eventName);
|
||||
@@ -26,9 +24,8 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Fire an event until the first non-null response is returned.
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @return array|null
|
||||
*/
|
||||
public function until($event, $payload = []);
|
||||
@@ -36,10 +33,9 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Fire an event and call the listeners.
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire($event, $payload = [], $halt = false);
|
||||
@@ -47,10 +43,9 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Fire an event and call the listeners.
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
* @return array|null
|
||||
*/
|
||||
public function dispatch($event, $payload = [], $halt = false);
|
||||
@@ -58,8 +53,7 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Get all of the listeners for a given event name.
|
||||
*
|
||||
* @param string $eventName
|
||||
*
|
||||
* @param string $eventName
|
||||
* @return array
|
||||
*/
|
||||
public function getListeners($eventName);
|
||||
@@ -67,8 +61,7 @@ interface DispatcherInterface
|
||||
/**
|
||||
* Remove a set of listeners from the dispatcher.
|
||||
*
|
||||
* @param string $event
|
||||
*
|
||||
* @param string $event
|
||||
* @return void
|
||||
*/
|
||||
public function forget($event);
|
||||
|
||||
@@ -21,7 +21,7 @@ class Logger
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param LoggerInterface|null $logger
|
||||
* @param LoggerInterface|null $logger
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger = null)
|
||||
{
|
||||
@@ -31,8 +31,7 @@ class Logger
|
||||
/**
|
||||
* Logs the given event.
|
||||
*
|
||||
* @param mixed $event
|
||||
*
|
||||
* @param mixed $event
|
||||
* @return void
|
||||
*/
|
||||
public function log($event)
|
||||
@@ -53,8 +52,7 @@ class Logger
|
||||
/**
|
||||
* Logs an authentication event.
|
||||
*
|
||||
* @param AuthEvent $event
|
||||
*
|
||||
* @param AuthEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function auth(AuthEvent $event)
|
||||
@@ -81,8 +79,7 @@ class Logger
|
||||
/**
|
||||
* Logs a model event.
|
||||
*
|
||||
* @param ModelEvent $event
|
||||
*
|
||||
* @param ModelEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function model(ModelEvent $event)
|
||||
@@ -106,8 +103,7 @@ class Logger
|
||||
/**
|
||||
* Logs a query event.
|
||||
*
|
||||
* @param QueryEvent $event
|
||||
*
|
||||
* @param QueryEvent $event
|
||||
* @return void
|
||||
*/
|
||||
public function query(QueryEvent $event)
|
||||
@@ -133,8 +129,7 @@ class Logger
|
||||
/**
|
||||
* Returns the operational name of the given event.
|
||||
*
|
||||
* @param mixed $event
|
||||
*
|
||||
* @param mixed $event
|
||||
* @return string
|
||||
*/
|
||||
protected function getOperationName($event)
|
||||
|
||||
@@ -14,7 +14,7 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param DispatcherInterface $dispatcher
|
||||
* @param DispatcherInterface $dispatcher
|
||||
*/
|
||||
public function __construct(DispatcherInterface $dispatcher)
|
||||
{
|
||||
@@ -24,9 +24,8 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Register an event listener with the dispatcher.
|
||||
*
|
||||
* @param string|array $events
|
||||
* @param mixed $listener
|
||||
*
|
||||
* @param string|array $events
|
||||
* @param mixed $listener
|
||||
* @return void
|
||||
*/
|
||||
public function listen($events, $listener)
|
||||
@@ -37,8 +36,7 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Determine if a given event has listeners.
|
||||
*
|
||||
* @param string $eventName
|
||||
*
|
||||
* @param string $eventName
|
||||
* @return bool
|
||||
*/
|
||||
public function hasListeners($eventName)
|
||||
@@ -49,9 +47,8 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Fire an event until the first non-null response is returned.
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @return null
|
||||
*/
|
||||
public function until($event, $payload = [])
|
||||
@@ -62,10 +59,9 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Fire an event and call the listeners.
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
* @return null
|
||||
*/
|
||||
public function fire($event, $payload = [], $halt = false)
|
||||
@@ -76,10 +72,9 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Fire an event and call the listeners.
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
*
|
||||
* @param string|object $event
|
||||
* @param mixed $payload
|
||||
* @param bool $halt
|
||||
* @return null
|
||||
*/
|
||||
public function dispatch($event, $payload = [], $halt = false)
|
||||
@@ -90,8 +85,7 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Get all of the listeners for a given event name.
|
||||
*
|
||||
* @param string $eventName
|
||||
*
|
||||
* @param string $eventName
|
||||
* @return array
|
||||
*/
|
||||
public function getListeners($eventName)
|
||||
@@ -102,8 +96,7 @@ class NullDispatcher implements DispatcherInterface
|
||||
/**
|
||||
* Remove a set of listeners from the dispatcher.
|
||||
*
|
||||
* @param string $event
|
||||
*
|
||||
* @param string $event
|
||||
* @return void
|
||||
*/
|
||||
public function forget($event)
|
||||
|
||||
@@ -148,8 +148,7 @@ trait HandlesConnection
|
||||
/**
|
||||
* Convert warnings to exceptions for the given operation.
|
||||
*
|
||||
* @param Closure $operation
|
||||
*
|
||||
* @param Closure $operation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -190,8 +189,7 @@ trait HandlesConnection
|
||||
/**
|
||||
* Determine if the failed operation should be bypassed.
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldBypassFailure($method)
|
||||
@@ -202,8 +200,7 @@ trait HandlesConnection
|
||||
/**
|
||||
* Determine if the error should be bypassed.
|
||||
*
|
||||
* @param string $error
|
||||
*
|
||||
* @param string $error
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldBypassError($error)
|
||||
@@ -226,9 +223,8 @@ trait HandlesConnection
|
||||
/**
|
||||
* Generates an LDAP connection string for each host given.
|
||||
*
|
||||
* @param string|array $hosts
|
||||
* @param string $port
|
||||
*
|
||||
* @param string|array $hosts
|
||||
* @param string $port
|
||||
* @return string
|
||||
*/
|
||||
protected function makeConnectionUris($hosts, $port)
|
||||
@@ -249,9 +245,8 @@ trait HandlesConnection
|
||||
/**
|
||||
* Assemble the host URI strings.
|
||||
*
|
||||
* @param array|string $hosts
|
||||
* @param string $port
|
||||
*
|
||||
* @param array|string $hosts
|
||||
* @param string $port
|
||||
* @return array
|
||||
*/
|
||||
protected function assembleHostUris($hosts, $port)
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace LdapRecord;
|
||||
|
||||
use LDAP\Connection as RawLdapConnection;
|
||||
|
||||
/** @psalm-suppress UndefinedClass */
|
||||
class Ldap implements LdapInterface
|
||||
{
|
||||
use HandlesConnection, DetectsErrors;
|
||||
@@ -24,8 +23,7 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-first-entry.php
|
||||
*
|
||||
* @param resource $searchResults
|
||||
*
|
||||
* @param resource $searchResults
|
||||
* @return resource
|
||||
*/
|
||||
public function getFirstEntry($searchResults)
|
||||
@@ -40,8 +38,7 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-next-entry.php
|
||||
*
|
||||
* @param resource $entry
|
||||
*
|
||||
* @param resource $entry
|
||||
* @return resource
|
||||
*/
|
||||
public function getNextEntry($entry)
|
||||
@@ -56,8 +53,7 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-get-attributes.php
|
||||
*
|
||||
* @param resource $entry
|
||||
*
|
||||
* @param resource $entry
|
||||
* @return array|false
|
||||
*/
|
||||
public function getAttributes($entry)
|
||||
@@ -72,8 +68,7 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-count-entries.php
|
||||
*
|
||||
* @param resource $searchResults
|
||||
*
|
||||
* @param resource $searchResults
|
||||
* @return int
|
||||
*/
|
||||
public function countEntries($searchResults)
|
||||
@@ -88,10 +83,9 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-compare.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $attribute
|
||||
* @param string $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function compare($dn, $attribute, $value)
|
||||
@@ -132,9 +126,8 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-get-values-len.php
|
||||
*
|
||||
* @param $entry
|
||||
* @param $attribute
|
||||
*
|
||||
* @param $entry
|
||||
* @param $attribute
|
||||
* @return array
|
||||
*/
|
||||
public function getValuesLen($entry, $attribute)
|
||||
@@ -167,8 +160,7 @@ class Ldap implements LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-set-rebind-proc.php
|
||||
*
|
||||
* @param callable $callback
|
||||
*
|
||||
* @param callable $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function setRebindCallback(callable $callback)
|
||||
@@ -304,7 +296,7 @@ class Ldap implements LdapInterface
|
||||
public function bind($username, $password)
|
||||
{
|
||||
return $this->bound = $this->executeFailableOperation(function () use ($username, $password) {
|
||||
return ldap_bind($this->connection, $username, html_entity_decode($password));
|
||||
return ldap_bind($this->connection, $username, $password ? html_entity_decode($password) : null);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -462,8 +454,7 @@ class Ldap implements LdapInterface
|
||||
/**
|
||||
* Extract the diagnostic code from the message.
|
||||
*
|
||||
* @param string $message
|
||||
*
|
||||
* @param string $message
|
||||
* @return string|bool
|
||||
*/
|
||||
public function extractDiagnosticCode($message)
|
||||
|
||||
@@ -9,28 +9,28 @@ interface LdapInterface
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PROTOCOL_SSL = 'ldaps://';
|
||||
public const PROTOCOL_SSL = 'ldaps://';
|
||||
|
||||
/**
|
||||
* The standard LDAP protocol string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PROTOCOL = 'ldap://';
|
||||
public const PROTOCOL = 'ldap://';
|
||||
|
||||
/**
|
||||
* The LDAP SSL port number.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PORT_SSL = 636;
|
||||
public const PORT_SSL = 636;
|
||||
|
||||
/**
|
||||
* The standard LDAP port number.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PORT = 389;
|
||||
public const PORT = 389;
|
||||
|
||||
/**
|
||||
* Various useful server control OID's.
|
||||
@@ -38,37 +38,36 @@ interface LdapInterface
|
||||
* @see https://ldap.com/ldap-oid-reference-guide/
|
||||
* @see http://msdn.microsoft.com/en-us/library/cc223359.aspx
|
||||
*/
|
||||
const OID_SERVER_START_TLS = '1.3.6.1.4.1.1466.20037';
|
||||
const OID_SERVER_PAGED_RESULTS = '1.2.840.113556.1.4.319';
|
||||
const OID_SERVER_SHOW_DELETED = '1.2.840.113556.1.4.417';
|
||||
const OID_SERVER_SORT = '1.2.840.113556.1.4.473';
|
||||
const OID_SERVER_CROSSDOM_MOVE_TARGET = '1.2.840.113556.1.4.521';
|
||||
const OID_SERVER_NOTIFICATION = '1.2.840.113556.1.4.528';
|
||||
const OID_SERVER_EXTENDED_DN = '1.2.840.113556.1.4.529';
|
||||
const OID_SERVER_LAZY_COMMIT = '1.2.840.113556.1.4.619';
|
||||
const OID_SERVER_SD_FLAGS = '1.2.840.113556.1.4.801';
|
||||
const OID_SERVER_TREE_DELETE = '1.2.840.113556.1.4.805';
|
||||
const OID_SERVER_DIRSYNC = '1.2.840.113556.1.4.841';
|
||||
const OID_SERVER_VERIFY_NAME = '1.2.840.113556.1.4.1338';
|
||||
const OID_SERVER_DOMAIN_SCOPE = '1.2.840.113556.1.4.1339';
|
||||
const OID_SERVER_SEARCH_OPTIONS = '1.2.840.113556.1.4.1340';
|
||||
const OID_SERVER_PERMISSIVE_MODIFY = '1.2.840.113556.1.4.1413';
|
||||
const OID_SERVER_ASQ = '1.2.840.113556.1.4.1504';
|
||||
const OID_SERVER_FAST_BIND = '1.2.840.113556.1.4.1781';
|
||||
const OID_SERVER_CONTROL_VLVREQUEST = '2.16.840.1.113730.3.4.9';
|
||||
public const OID_SERVER_START_TLS = '1.3.6.1.4.1.1466.20037';
|
||||
public const OID_SERVER_PAGED_RESULTS = '1.2.840.113556.1.4.319';
|
||||
public const OID_SERVER_SHOW_DELETED = '1.2.840.113556.1.4.417';
|
||||
public const OID_SERVER_SORT = '1.2.840.113556.1.4.473';
|
||||
public const OID_SERVER_CROSSDOM_MOVE_TARGET = '1.2.840.113556.1.4.521';
|
||||
public const OID_SERVER_NOTIFICATION = '1.2.840.113556.1.4.528';
|
||||
public const OID_SERVER_EXTENDED_DN = '1.2.840.113556.1.4.529';
|
||||
public const OID_SERVER_LAZY_COMMIT = '1.2.840.113556.1.4.619';
|
||||
public const OID_SERVER_SD_FLAGS = '1.2.840.113556.1.4.801';
|
||||
public const OID_SERVER_TREE_DELETE = '1.2.840.113556.1.4.805';
|
||||
public const OID_SERVER_DIRSYNC = '1.2.840.113556.1.4.841';
|
||||
public const OID_SERVER_VERIFY_NAME = '1.2.840.113556.1.4.1338';
|
||||
public const OID_SERVER_DOMAIN_SCOPE = '1.2.840.113556.1.4.1339';
|
||||
public const OID_SERVER_SEARCH_OPTIONS = '1.2.840.113556.1.4.1340';
|
||||
public const OID_SERVER_PERMISSIVE_MODIFY = '1.2.840.113556.1.4.1413';
|
||||
public const OID_SERVER_ASQ = '1.2.840.113556.1.4.1504';
|
||||
public const OID_SERVER_FAST_BIND = '1.2.840.113556.1.4.1781';
|
||||
public const OID_SERVER_CONTROL_VLVREQUEST = '2.16.840.1.113730.3.4.9';
|
||||
|
||||
/**
|
||||
* Query OID's.
|
||||
*
|
||||
* @see https://ldapwiki.com/wiki/LDAP_MATCHING_RULE_IN_CHAIN
|
||||
*/
|
||||
const OID_MATCHING_RULE_IN_CHAIN = '1.2.840.113556.1.4.1941';
|
||||
public const OID_MATCHING_RULE_IN_CHAIN = '1.2.840.113556.1.4.1941';
|
||||
|
||||
/**
|
||||
* Set the current connection to use SSL.
|
||||
*
|
||||
* @param bool $enabled
|
||||
*
|
||||
* @param bool $enabled
|
||||
* @return $this
|
||||
*/
|
||||
public function ssl();
|
||||
@@ -83,8 +82,7 @@ interface LdapInterface
|
||||
/**
|
||||
* Set the current connection to use TLS.
|
||||
*
|
||||
* @param bool $enabled
|
||||
*
|
||||
* @param bool $enabled
|
||||
* @return $this
|
||||
*/
|
||||
public function tls();
|
||||
@@ -138,8 +136,7 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-get-entries.php
|
||||
*
|
||||
* @param resource $searchResults
|
||||
*
|
||||
* @param resource $searchResults
|
||||
* @return array
|
||||
*/
|
||||
public function getEntries($searchResults);
|
||||
@@ -169,9 +166,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-set-option.php
|
||||
*
|
||||
* @param int $option
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param int $option
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function setOption($option, $value);
|
||||
@@ -179,8 +175,7 @@ interface LdapInterface
|
||||
/**
|
||||
* Set options on the current connection.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public function setOptions(array $options = []);
|
||||
@@ -190,9 +185,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.ldap-get-option.php
|
||||
*
|
||||
* @param int $option
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param int $option
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOption($option, &$value = null);
|
||||
@@ -213,9 +207,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-start-tls.php
|
||||
*
|
||||
* @param string|array $hosts
|
||||
* @param int $port
|
||||
*
|
||||
* @param string|array $hosts
|
||||
* @param int $port
|
||||
* @return resource|false
|
||||
*/
|
||||
public function connect($hosts = [], $port = 389);
|
||||
@@ -236,15 +229,14 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-search.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $filter
|
||||
* @param array $fields
|
||||
* @param bool $onlyAttributes
|
||||
* @param int $size
|
||||
* @param int $time
|
||||
* @param int $deref
|
||||
* @param array $serverControls
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $filter
|
||||
* @param array $fields
|
||||
* @param bool $onlyAttributes
|
||||
* @param int $size
|
||||
* @param int $time
|
||||
* @param int $deref
|
||||
* @param array $serverControls
|
||||
* @return resource
|
||||
*/
|
||||
public function search($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = LDAP_DEREF_NEVER, $serverControls = []);
|
||||
@@ -254,15 +246,14 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-list.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $filter
|
||||
* @param array $fields
|
||||
* @param bool $onlyAttributes
|
||||
* @param int $size
|
||||
* @param int $time
|
||||
* @param int $deref
|
||||
* @param array $serverControls
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $filter
|
||||
* @param array $fields
|
||||
* @param bool $onlyAttributes
|
||||
* @param int $size
|
||||
* @param int $time
|
||||
* @param int $deref
|
||||
* @param array $serverControls
|
||||
* @return resource
|
||||
*/
|
||||
public function listing($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = LDAP_DEREF_NEVER, $serverControls = []);
|
||||
@@ -272,15 +263,14 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-read.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $filter
|
||||
* @param array $fields
|
||||
* @param bool $onlyAttributes
|
||||
* @param int $size
|
||||
* @param int $time
|
||||
* @param int $deref
|
||||
* @param array $serverControls
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $filter
|
||||
* @param array $fields
|
||||
* @param bool $onlyAttributes
|
||||
* @param int $size
|
||||
* @param int $time
|
||||
* @param int $deref
|
||||
* @param array $serverControls
|
||||
* @return resource
|
||||
*/
|
||||
public function read($dn, $filter, array $fields, $onlyAttributes = false, $size = 0, $time = 0, $deref = LDAP_DEREF_NEVER, $serverControls = []);
|
||||
@@ -290,13 +280,12 @@ interface LdapInterface
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.ldap-parse-result.php
|
||||
*
|
||||
* @param resource $result
|
||||
* @param int $errorCode
|
||||
* @param ?string $dn
|
||||
* @param ?string $errorMessage
|
||||
* @param ?array $referrals
|
||||
* @param ?array $serverControls
|
||||
*
|
||||
* @param resource $result
|
||||
* @param int $errorCode
|
||||
* @param ?string $dn
|
||||
* @param ?string $errorMessage
|
||||
* @param ?array $referrals
|
||||
* @param ?array $serverControls
|
||||
* @return bool
|
||||
*/
|
||||
public function parseResult($result, &$errorCode, &$dn, &$errorMessage, &$referrals, &$serverControls = []);
|
||||
@@ -307,9 +296,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-bind.php
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $username
|
||||
* @param string $password
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -321,9 +309,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-add.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -335,8 +322,7 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-delete.php
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @param string $dn
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -348,11 +334,10 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-rename.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $newRdn
|
||||
* @param string $newParent
|
||||
* @param bool $deleteOldRdn
|
||||
*
|
||||
* @param string $dn
|
||||
* @param string $newRdn
|
||||
* @param string $newParent
|
||||
* @param bool $deleteOldRdn
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -364,9 +349,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-modify.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -378,9 +362,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-modify-batch.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $values
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $values
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -392,9 +375,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-mod-add.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -406,9 +388,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-mod-replace.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -420,9 +401,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-mod-del.php
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
*
|
||||
* @param string $dn
|
||||
* @param array $entry
|
||||
* @return bool
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -434,10 +414,9 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-control-paged-result.php
|
||||
*
|
||||
* @param int $pageSize
|
||||
* @param bool $isCritical
|
||||
* @param string $cookie
|
||||
*
|
||||
* @param int $pageSize
|
||||
* @param bool $isCritical
|
||||
* @param string $cookie
|
||||
* @return bool
|
||||
*/
|
||||
public function controlPagedResult($pageSize = 1000, $isCritical = false, $cookie = '');
|
||||
@@ -447,9 +426,8 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-control-paged-result-response.php
|
||||
*
|
||||
* @param resource $result
|
||||
* @param string $cookie
|
||||
*
|
||||
* @param resource $result
|
||||
* @param string $cookie
|
||||
* @return bool
|
||||
*/
|
||||
public function controlPagedResultResponse($result, &$cookie);
|
||||
@@ -459,8 +437,7 @@ interface LdapInterface
|
||||
*
|
||||
* @see https://www.php.net/manual/en/function.ldap-free-result.php
|
||||
*
|
||||
* @param resource $result
|
||||
*
|
||||
* @param resource $result
|
||||
* @return bool
|
||||
*/
|
||||
public function freeResult($result);
|
||||
@@ -479,8 +456,7 @@ interface LdapInterface
|
||||
*
|
||||
* @see http://php.net/manual/en/function.ldap-err2str.php
|
||||
*
|
||||
* @param int $number
|
||||
*
|
||||
* @param int $number
|
||||
* @return string
|
||||
*/
|
||||
public function err2Str($number);
|
||||
|
||||
@@ -16,9 +16,8 @@ class LdapRecordException extends Exception
|
||||
/**
|
||||
* Create a new Bind Exception with a detailed connection error.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @param DetailedError|null $error
|
||||
*
|
||||
* @param Exception $e
|
||||
* @param DetailedError|null $error
|
||||
* @return $this
|
||||
*/
|
||||
public static function withDetailedError(Exception $e, DetailedError $error = null)
|
||||
@@ -29,8 +28,7 @@ class LdapRecordException extends Exception
|
||||
/**
|
||||
* Set the detailed error.
|
||||
*
|
||||
* @param DetailedError|null $error
|
||||
*
|
||||
* @param DetailedError|null $error
|
||||
* @return $this
|
||||
*/
|
||||
public function setDetailedError(DetailedError $error = null)
|
||||
|
||||
@@ -9,10 +9,9 @@ trait HasPrimaryGroup
|
||||
/**
|
||||
* Returns a new has one primary group relationship.
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
* @return HasOnePrimaryGroup
|
||||
*/
|
||||
public function hasOnePrimaryGroup($related, $relationKey, $foreignKey = 'primarygroupid')
|
||||
|
||||
@@ -9,6 +9,7 @@ use LdapRecord\Models\Entry as BaseEntry;
|
||||
use LdapRecord\Models\Events\Updated;
|
||||
use LdapRecord\Models\Types\ActiveDirectory;
|
||||
use LdapRecord\Query\Model\ActiveDirectoryBuilder;
|
||||
use LdapRecord\Support\Arr;
|
||||
|
||||
/** @mixin ActiveDirectoryBuilder */
|
||||
class Entry extends BaseEntry implements ActiveDirectory
|
||||
@@ -50,20 +51,46 @@ class Entry extends BaseEntry implements ActiveDirectory
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getConvertedSid()
|
||||
public function getConvertedSid($sid = null)
|
||||
{
|
||||
try {
|
||||
return (string) new Sid($this->getObjectSid());
|
||||
return (string) $this->newObjectSid(
|
||||
$sid ?? $this->getObjectSid()
|
||||
);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBinarySid($sid = null)
|
||||
{
|
||||
try {
|
||||
return $this->newObjectSid(
|
||||
$sid ?? $this->getObjectSid()
|
||||
)->getBinary();
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new object Sid instance.
|
||||
*
|
||||
* @param string $value
|
||||
* @return Sid
|
||||
*/
|
||||
protected function newObjectSid($value)
|
||||
{
|
||||
return new Sid($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new query builder.
|
||||
*
|
||||
* @param Connection $connection
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @return ActiveDirectoryBuilder
|
||||
*/
|
||||
public function newQueryBuilder(Connection $connection)
|
||||
@@ -84,8 +111,7 @@ class Entry extends BaseEntry implements ActiveDirectory
|
||||
/**
|
||||
* Restore a deleted object.
|
||||
*
|
||||
* @param string|null $newParentDn
|
||||
*
|
||||
* @param string|null $newParentDn
|
||||
* @return bool
|
||||
*
|
||||
* @throws \LdapRecord\LdapRecordException
|
||||
@@ -114,24 +140,6 @@ class Entry extends BaseEntry implements ActiveDirectory
|
||||
$this->save(['isDeleted' => null]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the RootDSE (AD schema) record from the directory.
|
||||
*
|
||||
* @param string|null $connection
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @throws \LdapRecord\Models\ModelNotFoundException
|
||||
*/
|
||||
public static function getRootDse($connection = null)
|
||||
{
|
||||
return static::on($connection ?? (new static())->getConnectionName())
|
||||
->in(null)
|
||||
->read()
|
||||
->whereHas('objectclass')
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the objects restore location.
|
||||
*
|
||||
@@ -143,22 +151,50 @@ class Entry extends BaseEntry implements ActiveDirectory
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts attributes for JSON serialization.
|
||||
*
|
||||
* @param array $attributes
|
||||
* Convert the attributes for JSON serialization.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function convertAttributesForJson(array $attributes = [])
|
||||
{
|
||||
$attributes = parent::convertAttributesForJson($attributes);
|
||||
|
||||
if ($this->hasAttribute($this->sidKey)) {
|
||||
// If the model has a SID set, we need to convert it due to it being in
|
||||
// binary. Otherwise we will receive a JSON serialization exception.
|
||||
return array_replace($attributes, [
|
||||
$this->sidKey => [$this->getConvertedSid()],
|
||||
]);
|
||||
// If the model has a SID set, we need to convert it to its
|
||||
// string format, due to it being in binary. Otherwise
|
||||
// we will receive a JSON serialization exception.
|
||||
if (isset($attributes[$this->sidKey])) {
|
||||
$attributes[$this->sidKey] = [$this->getConvertedSid(
|
||||
Arr::first($attributes[$this->sidKey])
|
||||
)];
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the attributes from JSON serialization.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function convertAttributesFromJson(array $attributes = [])
|
||||
{
|
||||
$attributes = parent::convertAttributesFromJson($attributes);
|
||||
|
||||
// Here we are converting the model's GUID and SID attributes
|
||||
// back to their original values from serialization, so that
|
||||
// their original value may be used and compared against.
|
||||
if (isset($attributes[$this->guidKey])) {
|
||||
$attributes[$this->guidKey] = [$this->getBinaryGuid(
|
||||
Arr::first($attributes[$this->guidKey])
|
||||
)];
|
||||
}
|
||||
|
||||
if (isset($attributes[$this->sidKey])) {
|
||||
$attributes[$this->sidKey] = [$this->getBinarySid(
|
||||
Arr::first($attributes[$this->sidKey])
|
||||
)];
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
|
||||
@@ -10,8 +10,7 @@ class HasOnePrimaryGroup extends HasOne
|
||||
/**
|
||||
* Get the foreign model by the given value.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return Model|null
|
||||
*/
|
||||
protected function getForeignModelByValue($value)
|
||||
@@ -26,8 +25,7 @@ class HasOnePrimaryGroup extends HasOne
|
||||
*
|
||||
* Retrieves the last RID from the models Object SID.
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Model $model
|
||||
* @return string
|
||||
*/
|
||||
protected function getForeignValueFromModel(Model $model)
|
||||
|
||||
@@ -11,9 +11,8 @@ class HasServerRoleAttribute implements Scope
|
||||
/**
|
||||
* Includes condition of having a serverRole attribute.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $query, Model $model)
|
||||
|
||||
@@ -12,9 +12,8 @@ class InConfigurationContext implements Scope
|
||||
/**
|
||||
* Refines the base dn to be inside the configuration context.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*
|
||||
* @throws \LdapRecord\Models\ModelNotFoundException
|
||||
@@ -27,8 +26,7 @@ class InConfigurationContext implements Scope
|
||||
/**
|
||||
* Get the LDAP server configuration naming context distinguished name.
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Model $model
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \LdapRecord\Models\ModelNotFoundException
|
||||
|
||||
@@ -11,9 +11,8 @@ class RejectComputerObjectClass implements Scope
|
||||
/**
|
||||
* Prevent computer objects from being included in results.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $query, Model $model)
|
||||
|
||||
@@ -6,6 +6,7 @@ use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use LdapRecord\Models\ActiveDirectory\Concerns\HasPrimaryGroup;
|
||||
use LdapRecord\Models\ActiveDirectory\Scopes\RejectComputerObjectClass;
|
||||
use LdapRecord\Models\Attributes\AccountControl;
|
||||
use LdapRecord\Models\Concerns\CanAuthenticate;
|
||||
use LdapRecord\Models\Concerns\HasPassword;
|
||||
use LdapRecord\Query\Model\Builder;
|
||||
@@ -71,6 +72,38 @@ class User extends Entry implements Authenticatable
|
||||
static::addGlobalScope(new RejectComputerObjectClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user's account is enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEnabled()
|
||||
{
|
||||
return ! $this->isDisabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user's account is disabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isDisabled()
|
||||
{
|
||||
return $this->accountControl()->has(AccountControl::ACCOUNTDISABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's account control.
|
||||
*
|
||||
* @return AccountControl
|
||||
*/
|
||||
public function accountControl()
|
||||
{
|
||||
return new AccountControl(
|
||||
$this->getFirstAttribute('userAccountControl')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The groups relationship.
|
||||
*
|
||||
@@ -110,8 +143,7 @@ class User extends Entry implements Authenticatable
|
||||
/**
|
||||
* Scopes the query to exchange mailbox users.
|
||||
*
|
||||
* @param Builder $query
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeWhereHasMailbox(Builder $query)
|
||||
@@ -122,8 +154,7 @@ class User extends Entry implements Authenticatable
|
||||
/**
|
||||
* Scopes the query to users having a lockout value set.
|
||||
*
|
||||
* @param Builder $query
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return Builder
|
||||
*/
|
||||
public function scopeWhereHasLockout(Builder $query)
|
||||
@@ -137,9 +168,8 @@ class User extends Entry implements Authenticatable
|
||||
* @see https://ldapwiki.com/wiki/Active%20Directory%20Account%20Lockout
|
||||
* @see https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/account-lockout-duration
|
||||
*
|
||||
* @param string|int $localTimezone
|
||||
* @param int|null $durationInMinutes
|
||||
*
|
||||
* @param string|int $localTimezone
|
||||
* @param int|null $durationInMinutes
|
||||
* @return bool
|
||||
*/
|
||||
public function isLockedOut($localTimezone, $durationInMinutes = null)
|
||||
|
||||
@@ -6,49 +6,49 @@ use ReflectionClass;
|
||||
|
||||
class AccountControl
|
||||
{
|
||||
const SCRIPT = 1;
|
||||
public const SCRIPT = 1;
|
||||
|
||||
const ACCOUNTDISABLE = 2;
|
||||
public const ACCOUNTDISABLE = 2;
|
||||
|
||||
const HOMEDIR_REQUIRED = 8;
|
||||
public const HOMEDIR_REQUIRED = 8;
|
||||
|
||||
const LOCKOUT = 16;
|
||||
public const LOCKOUT = 16;
|
||||
|
||||
const PASSWD_NOTREQD = 32;
|
||||
public const PASSWD_NOTREQD = 32;
|
||||
|
||||
const PASSWD_CANT_CHANGE = 64;
|
||||
public const PASSWD_CANT_CHANGE = 64;
|
||||
|
||||
const ENCRYPTED_TEXT_PWD_ALLOWED = 128;
|
||||
public const ENCRYPTED_TEXT_PWD_ALLOWED = 128;
|
||||
|
||||
const TEMP_DUPLICATE_ACCOUNT = 256;
|
||||
public const TEMP_DUPLICATE_ACCOUNT = 256;
|
||||
|
||||
const NORMAL_ACCOUNT = 512;
|
||||
public const NORMAL_ACCOUNT = 512;
|
||||
|
||||
const INTERDOMAIN_TRUST_ACCOUNT = 2048;
|
||||
public const INTERDOMAIN_TRUST_ACCOUNT = 2048;
|
||||
|
||||
const WORKSTATION_TRUST_ACCOUNT = 4096;
|
||||
public const WORKSTATION_TRUST_ACCOUNT = 4096;
|
||||
|
||||
const SERVER_TRUST_ACCOUNT = 8192;
|
||||
public const SERVER_TRUST_ACCOUNT = 8192;
|
||||
|
||||
const DONT_EXPIRE_PASSWORD = 65536;
|
||||
public const DONT_EXPIRE_PASSWORD = 65536;
|
||||
|
||||
const MNS_LOGON_ACCOUNT = 131072;
|
||||
public const MNS_LOGON_ACCOUNT = 131072;
|
||||
|
||||
const SMARTCARD_REQUIRED = 262144;
|
||||
public const SMARTCARD_REQUIRED = 262144;
|
||||
|
||||
const TRUSTED_FOR_DELEGATION = 524288;
|
||||
public const TRUSTED_FOR_DELEGATION = 524288;
|
||||
|
||||
const NOT_DELEGATED = 1048576;
|
||||
public const NOT_DELEGATED = 1048576;
|
||||
|
||||
const USE_DES_KEY_ONLY = 2097152;
|
||||
public const USE_DES_KEY_ONLY = 2097152;
|
||||
|
||||
const DONT_REQ_PREAUTH = 4194304;
|
||||
public const DONT_REQ_PREAUTH = 4194304;
|
||||
|
||||
const PASSWORD_EXPIRED = 8388608;
|
||||
public const PASSWORD_EXPIRED = 8388608;
|
||||
|
||||
const TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216;
|
||||
public const TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216;
|
||||
|
||||
const PARTIAL_SECRETS_ACCOUNT = 67108864;
|
||||
public const PARTIAL_SECRETS_ACCOUNT = 67108864;
|
||||
|
||||
/**
|
||||
* The account control flag values.
|
||||
@@ -60,7 +60,7 @@ class AccountControl
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ?int $flag
|
||||
* @param ?int $flag
|
||||
*/
|
||||
public function __construct($flag = null)
|
||||
{
|
||||
@@ -92,8 +92,7 @@ class AccountControl
|
||||
/**
|
||||
* Add the flag to the account control values.
|
||||
*
|
||||
* @param int $flag
|
||||
*
|
||||
* @param int $flag
|
||||
* @return $this
|
||||
*/
|
||||
public function add($flag)
|
||||
@@ -108,8 +107,7 @@ class AccountControl
|
||||
/**
|
||||
* Remove the flag from the account control.
|
||||
*
|
||||
* @param int $flag
|
||||
*
|
||||
* @param int $flag
|
||||
* @return $this
|
||||
*/
|
||||
public function remove($flag)
|
||||
@@ -122,8 +120,7 @@ class AccountControl
|
||||
/**
|
||||
* Extract and apply the flag.
|
||||
*
|
||||
* @param int $flag
|
||||
*
|
||||
* @param int $flag
|
||||
* @return void
|
||||
*/
|
||||
public function apply($flag)
|
||||
@@ -134,8 +131,7 @@ class AccountControl
|
||||
/**
|
||||
* Determine if the account control contains the given UAC flag(s).
|
||||
*
|
||||
* @param int $flag
|
||||
*
|
||||
* @param int $flag
|
||||
* @return bool
|
||||
*/
|
||||
public function has($flag)
|
||||
@@ -154,8 +150,7 @@ class AccountControl
|
||||
/**
|
||||
* Determine if the account control does not contain the given UAC flag(s).
|
||||
*
|
||||
* @param int $flag
|
||||
*
|
||||
* @param int $flag
|
||||
* @return bool
|
||||
*/
|
||||
public function doesntHave($flag)
|
||||
@@ -441,8 +436,7 @@ class AccountControl
|
||||
/**
|
||||
* Set the account control values.
|
||||
*
|
||||
* @param array<int, int> $flags
|
||||
*
|
||||
* @param array<int, int> $flags
|
||||
* @return void
|
||||
*/
|
||||
public function setValues(array $flags)
|
||||
@@ -483,8 +477,7 @@ class AccountControl
|
||||
/**
|
||||
* Extracts the given flag into an array of flags used.
|
||||
*
|
||||
* @param int $flag
|
||||
*
|
||||
* @param int $flag
|
||||
* @return array
|
||||
*/
|
||||
public function extractFlags($flag)
|
||||
|
||||
@@ -19,7 +19,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|null $value
|
||||
* @param string|null $value
|
||||
*/
|
||||
public function __construct($value = null)
|
||||
{
|
||||
@@ -39,8 +39,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Alias of the "build" method.
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return DistinguishedNameBuilder
|
||||
*/
|
||||
public static function of($value = null)
|
||||
@@ -51,8 +50,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Get a new DN builder object from the given DN.
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return DistinguishedNameBuilder
|
||||
*/
|
||||
public static function build($value = null)
|
||||
@@ -63,8 +61,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Make a new distinguished name instance.
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return static
|
||||
*/
|
||||
public static function make($value = null)
|
||||
@@ -75,8 +72,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Determine if the given value is a valid distinguished name.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid($value)
|
||||
@@ -87,8 +83,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Explode a distinguished name into relative distinguished names.
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @param string $dn
|
||||
* @return array
|
||||
*/
|
||||
public static function explode($dn)
|
||||
@@ -111,8 +106,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Un-escapes a hexadecimal string into its original string representation.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
public static function unescape($value)
|
||||
@@ -125,8 +119,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Explode the RDN into an attribute and value.
|
||||
*
|
||||
* @param string $rdn
|
||||
*
|
||||
* @param string $rdn
|
||||
* @return array
|
||||
*/
|
||||
public static function explodeRdn($rdn)
|
||||
@@ -137,8 +130,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Implode the component attribute and value into an RDN.
|
||||
*
|
||||
* @param string $rdn
|
||||
*
|
||||
* @param string $rdn
|
||||
* @return string
|
||||
*/
|
||||
public static function makeRdn(array $component)
|
||||
@@ -159,8 +151,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Set the underlying value.
|
||||
*
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|null $value
|
||||
* @return $this
|
||||
*/
|
||||
public function set($value)
|
||||
@@ -337,8 +328,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Determine if the current distinguished name is a parent of the given child.
|
||||
*
|
||||
* @param DistinguishedName $child
|
||||
*
|
||||
* @param DistinguishedName $child
|
||||
* @return bool
|
||||
*/
|
||||
public function isParentOf(self $child)
|
||||
@@ -349,8 +339,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Determine if the current distinguished name is a child of the given parent.
|
||||
*
|
||||
* @param DistinguishedName $parent
|
||||
*
|
||||
* @param DistinguishedName $parent
|
||||
* @return bool
|
||||
*/
|
||||
public function isChildOf(self $parent)
|
||||
@@ -370,8 +359,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Determine if the current distinguished name is an ancestor of the descendant.
|
||||
*
|
||||
* @param DistinguishedName $descendant
|
||||
*
|
||||
* @param DistinguishedName $descendant
|
||||
* @return bool
|
||||
*/
|
||||
public function isAncestorOf(self $descendant)
|
||||
@@ -382,8 +370,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Determine if the current distinguished name is a descendant of the ancestor.
|
||||
*
|
||||
* @param DistinguishedName $ancestor
|
||||
*
|
||||
* @param DistinguishedName $ancestor
|
||||
* @return bool
|
||||
*/
|
||||
public function isDescendantOf(self $ancestor)
|
||||
@@ -407,9 +394,8 @@ class DistinguishedName
|
||||
/**
|
||||
* Compare whether the two distinguished name values are equal.
|
||||
*
|
||||
* @param array $values
|
||||
* @param array $other
|
||||
*
|
||||
* @param array $values
|
||||
* @param array $other
|
||||
* @return bool
|
||||
*/
|
||||
protected function compare(array $values, array $other)
|
||||
@@ -420,8 +406,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Recase the array values.
|
||||
*
|
||||
* @param array $values
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
protected function recase(array $values)
|
||||
@@ -432,8 +417,7 @@ class DistinguishedName
|
||||
/**
|
||||
* Normalize the string value.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function normalize($value)
|
||||
|
||||
@@ -26,7 +26,7 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|null $value
|
||||
* @param string|null $value
|
||||
*/
|
||||
public function __construct($dn = null)
|
||||
{
|
||||
@@ -38,9 +38,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Forward missing method calls onto the Distinguished Name object.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
@@ -61,9 +60,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Prepend an RDN onto the DN.
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
* @return $this
|
||||
*/
|
||||
public function prepend($attribute, $value = null)
|
||||
@@ -79,9 +77,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Append an RDN onto the DN.
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
* @return $this
|
||||
*/
|
||||
public function append($attribute, $value = null)
|
||||
@@ -97,9 +94,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Componentize the attribute and value.
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
* @return array
|
||||
*/
|
||||
protected function componentize($attribute, $value = null)
|
||||
@@ -125,8 +121,7 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Make a componentized array by exploding the value if it's a string.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return array
|
||||
*/
|
||||
protected function makeComponentizedArray($value)
|
||||
@@ -137,9 +132,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Make an appendable component array from the attribute and value.
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
*
|
||||
* @param string|array $attribute
|
||||
* @param string|null $value
|
||||
* @return array
|
||||
*/
|
||||
protected function makeAppendableComponent($attribute, $value = null)
|
||||
@@ -150,9 +144,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Pop an RDN off of the end of the DN.
|
||||
*
|
||||
* @param int $amount
|
||||
* @param array $removed
|
||||
*
|
||||
* @param int $amount
|
||||
* @param array $removed
|
||||
* @return $this
|
||||
*/
|
||||
public function pop($amount = 1, &$removed = [])
|
||||
@@ -167,9 +160,8 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Shift an RDN off of the beginning of the DN.
|
||||
*
|
||||
* @param int $amount
|
||||
* @param array $removed
|
||||
*
|
||||
* @param int $amount
|
||||
* @param array $removed
|
||||
* @return $this
|
||||
*/
|
||||
public function shift($amount = 1, &$removed = [])
|
||||
@@ -196,8 +188,7 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Get the components of the DN.
|
||||
*
|
||||
* @param null|string $type
|
||||
*
|
||||
* @param null|string $type
|
||||
* @return array
|
||||
*/
|
||||
public function components($type = null)
|
||||
@@ -210,8 +201,7 @@ class DistinguishedNameBuilder
|
||||
/**
|
||||
* Get the components of a particular type.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
protected function componentsOfType($type)
|
||||
|
||||
@@ -28,9 +28,9 @@ class EscapedValue
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
* @param string $value
|
||||
* @param string $ignore
|
||||
* @param int $flags
|
||||
*/
|
||||
public function __construct($value, $ignore = '', $flags = 0)
|
||||
{
|
||||
@@ -72,8 +72,7 @@ class EscapedValue
|
||||
/**
|
||||
* Set the characters to exclude from being escaped.
|
||||
*
|
||||
* @param string $characters
|
||||
*
|
||||
* @param string $characters
|
||||
* @return $this
|
||||
*/
|
||||
public function ignore($characters)
|
||||
|
||||
@@ -50,8 +50,7 @@ class Guid
|
||||
/**
|
||||
* Determines if the specified GUID is valid.
|
||||
*
|
||||
* @param string $guid
|
||||
*
|
||||
* @param string $guid
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid($guid)
|
||||
@@ -62,7 +61,7 @@ class Guid
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
@@ -128,8 +127,7 @@ class Guid
|
||||
/**
|
||||
* Returns the string variant of a binary GUID.
|
||||
*
|
||||
* @param string $binary
|
||||
*
|
||||
* @param string $binary
|
||||
* @return string|null
|
||||
*/
|
||||
protected function binaryGuidToString($binary)
|
||||
@@ -144,10 +142,9 @@ class Guid
|
||||
*
|
||||
* @see https://github.com/ldaptools/ldaptools
|
||||
*
|
||||
* @param string $hex The full hex string.
|
||||
* @param array $sections An array of start and length (unless octet is true, then length is always 2).
|
||||
* @param bool $octet Whether this is for octet string form.
|
||||
*
|
||||
* @param string $hex The full hex string.
|
||||
* @param array $sections An array of start and length (unless octet is true, then length is always 2).
|
||||
* @param bool $octet Whether this is for octet string form.
|
||||
* @return string The concatenated sections in upper-case.
|
||||
*/
|
||||
protected function parseSection($hex, array $sections, $octet = false)
|
||||
|
||||
@@ -7,8 +7,7 @@ class MbString
|
||||
/**
|
||||
* Get the integer value of a specific character.
|
||||
*
|
||||
* @param $string
|
||||
*
|
||||
* @param $string
|
||||
* @return int
|
||||
*/
|
||||
public static function ord($string)
|
||||
@@ -27,8 +26,7 @@ class MbString
|
||||
/**
|
||||
* Get the character for a specific integer value.
|
||||
*
|
||||
* @param $int
|
||||
*
|
||||
* @param $int
|
||||
* @return string
|
||||
*/
|
||||
public static function chr($int)
|
||||
@@ -43,8 +41,7 @@ class MbString
|
||||
/**
|
||||
* Split a string into its individual characters and return it as an array.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return string[]
|
||||
*/
|
||||
public static function split($value)
|
||||
@@ -55,8 +52,7 @@ class MbString
|
||||
/**
|
||||
* Detects if the given string is UTF 8.
|
||||
*
|
||||
* @param $string
|
||||
*
|
||||
* @param $string
|
||||
* @return string|false
|
||||
*/
|
||||
public static function isUtf8($string)
|
||||
|
||||
@@ -8,15 +8,14 @@ use ReflectionMethod;
|
||||
|
||||
class Password
|
||||
{
|
||||
const CRYPT_SALT_TYPE_MD5 = 1;
|
||||
const CRYPT_SALT_TYPE_SHA256 = 5;
|
||||
const CRYPT_SALT_TYPE_SHA512 = 6;
|
||||
public const CRYPT_SALT_TYPE_MD5 = 1;
|
||||
public const CRYPT_SALT_TYPE_SHA256 = 5;
|
||||
public const CRYPT_SALT_TYPE_SHA512 = 6;
|
||||
|
||||
/**
|
||||
* Make an encoded password for transmission over LDAP.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function encode($password)
|
||||
@@ -27,9 +26,8 @@ class Password
|
||||
/**
|
||||
* Make a salted md5 password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function smd5($password, $salt = null)
|
||||
@@ -40,9 +38,8 @@ class Password
|
||||
/**
|
||||
* Make a salted SHA password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function ssha($password, $salt = null)
|
||||
@@ -53,9 +50,8 @@ class Password
|
||||
/**
|
||||
* Make a salted SSHA256 password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function ssha256($password, $salt = null)
|
||||
@@ -66,9 +62,8 @@ class Password
|
||||
/**
|
||||
* Make a salted SSHA384 password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function ssha384($password, $salt = null)
|
||||
@@ -79,9 +74,8 @@ class Password
|
||||
/**
|
||||
* Make a salted SSHA512 password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param null|string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function ssha512($password, $salt = null)
|
||||
@@ -92,8 +86,7 @@ class Password
|
||||
/**
|
||||
* Make a non-salted SHA password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function sha($password)
|
||||
@@ -104,8 +97,7 @@ class Password
|
||||
/**
|
||||
* Make a non-salted SHA256 password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function sha256($password)
|
||||
@@ -116,8 +108,7 @@ class Password
|
||||
/**
|
||||
* Make a non-salted SHA384 password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function sha384($password)
|
||||
@@ -128,8 +119,7 @@ class Password
|
||||
/**
|
||||
* Make a non-salted SHA512 password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function sha512($password)
|
||||
@@ -140,8 +130,7 @@ class Password
|
||||
/**
|
||||
* Make a non-salted md5 password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function md5($password)
|
||||
@@ -149,12 +138,22 @@ class Password
|
||||
return '{MD5}'.static::makeHash($password, 'md5');
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a non-salted NThash password.
|
||||
*
|
||||
* @param string $password
|
||||
* @return string
|
||||
*/
|
||||
public static function nthash($password)
|
||||
{
|
||||
return '{NTHASH}'.strtoupper(hash('md4', iconv('UTF-8', 'UTF-16LE', $password)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Crypt password with an MD5 salt.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function md5Crypt($password, $salt = null)
|
||||
@@ -165,9 +164,8 @@ class Password
|
||||
/**
|
||||
* Crypt password with a SHA256 salt.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function sha256Crypt($password, $salt = null)
|
||||
@@ -178,9 +176,8 @@ class Password
|
||||
/**
|
||||
* Crypt a password with a SHA512 salt.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
* @return string
|
||||
*/
|
||||
public static function sha512Crypt($password, $salt = null)
|
||||
@@ -191,11 +188,10 @@ class Password
|
||||
/**
|
||||
* Make a new password hash.
|
||||
*
|
||||
* @param string $password The password to make a hash of.
|
||||
* @param string $method The hash function to use.
|
||||
* @param string|null $algo The algorithm to use for hashing.
|
||||
* @param string|null $salt The salt to append onto the hash.
|
||||
*
|
||||
* @param string $password The password to make a hash of.
|
||||
* @param string $method The hash function to use.
|
||||
* @param string|null $algo The algorithm to use for hashing.
|
||||
* @param string|null $salt The salt to append onto the hash.
|
||||
* @return string
|
||||
*/
|
||||
protected static function makeHash($password, $method, $algo = null, $salt = null)
|
||||
@@ -208,10 +204,9 @@ class Password
|
||||
/**
|
||||
* Make a hashed password.
|
||||
*
|
||||
* @param string $password
|
||||
* @param int $type
|
||||
* @param null|string $salt
|
||||
*
|
||||
* @param string $password
|
||||
* @param int $type
|
||||
* @param null|string $salt
|
||||
* @return string
|
||||
*/
|
||||
protected static function makeCrypt($password, $type, $salt = null)
|
||||
@@ -222,8 +217,7 @@ class Password
|
||||
/**
|
||||
* Make a salt for the crypt() method using the given type.
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @param int $type
|
||||
* @return string
|
||||
*/
|
||||
protected static function makeCryptSalt($type)
|
||||
@@ -242,8 +236,7 @@ class Password
|
||||
/**
|
||||
* Determine the crypt prefix and length.
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @param int $type
|
||||
* @return array
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
@@ -265,8 +258,7 @@ class Password
|
||||
/**
|
||||
* Attempt to retrieve the hash method used for the password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return string|void
|
||||
*/
|
||||
public static function getHashMethod($password)
|
||||
@@ -281,8 +273,7 @@ class Password
|
||||
/**
|
||||
* Attempt to retrieve the hash method and algorithm used for the password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @param string $password
|
||||
* @return array|void
|
||||
*/
|
||||
public static function getHashMethodAndAlgo($password)
|
||||
@@ -319,8 +310,7 @@ class Password
|
||||
/**
|
||||
* Determine if the hash method requires a salt to be given.
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
|
||||
@@ -17,8 +17,7 @@ class Sid
|
||||
/**
|
||||
* Determines if the specified SID is valid.
|
||||
*
|
||||
* @param string $sid
|
||||
*
|
||||
* @param string $sid
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValid($sid)
|
||||
@@ -29,7 +28,7 @@ class Sid
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
@@ -90,8 +89,7 @@ class Sid
|
||||
/**
|
||||
* Returns the string variant of a binary SID.
|
||||
*
|
||||
* @param string $binary
|
||||
*
|
||||
* @param string $binary
|
||||
* @return string|null
|
||||
*/
|
||||
protected function binarySidToString($binary)
|
||||
|
||||
@@ -7,7 +7,7 @@ class TSProperty
|
||||
/**
|
||||
* Nibble control values. The first value for each is if the nibble is <= 9, otherwise the second value is used.
|
||||
*/
|
||||
const NIBBLE_CONTROL = [
|
||||
public const NIBBLE_CONTROL = [
|
||||
'X' => ['001011', '011010'],
|
||||
'Y' => ['001110', '011010'],
|
||||
];
|
||||
@@ -15,12 +15,12 @@ class TSProperty
|
||||
/**
|
||||
* The nibble header.
|
||||
*/
|
||||
const NIBBLE_HEADER = '1110';
|
||||
public const NIBBLE_HEADER = '1110';
|
||||
|
||||
/**
|
||||
* Conversion factor needed for time values in the TSPropertyArray (stored in microseconds).
|
||||
*/
|
||||
const TIME_CONVERSION = 60 * 1000;
|
||||
public const TIME_CONVERSION = 60 * 1000;
|
||||
|
||||
/**
|
||||
* A simple map to help determine how the property needs to be decoded/encoded from/to its binary value.
|
||||
@@ -85,7 +85,7 @@ class TSProperty
|
||||
/**
|
||||
* Pass binary TSProperty data to construct its object representation.
|
||||
*
|
||||
* @param string|null $value
|
||||
* @param string|null $value
|
||||
*/
|
||||
public function __construct($value = null)
|
||||
{
|
||||
@@ -97,8 +97,7 @@ class TSProperty
|
||||
/**
|
||||
* Set the name for the TSProperty.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @param string $name
|
||||
* @return TSProperty
|
||||
*/
|
||||
public function setName($name)
|
||||
@@ -121,8 +120,7 @@ class TSProperty
|
||||
/**
|
||||
* Set the value for the TSProperty.
|
||||
*
|
||||
* @param string|int $value
|
||||
*
|
||||
* @param string|int $value
|
||||
* @return TSProperty
|
||||
*/
|
||||
public function setValue($value)
|
||||
@@ -169,7 +167,7 @@ class TSProperty
|
||||
/**
|
||||
* Given a TSProperty blob, decode the name/value/type/etc.
|
||||
*
|
||||
* @param string $tsProperty
|
||||
* @param string $tsProperty
|
||||
*/
|
||||
protected function decode($tsProperty)
|
||||
{
|
||||
@@ -186,9 +184,8 @@ class TSProperty
|
||||
/**
|
||||
* Based on the property name/value in question, get its encoded form.
|
||||
*
|
||||
* @param string $propName
|
||||
* @param string|int $propValue
|
||||
*
|
||||
* @param string $propName
|
||||
* @param string|int $propValue
|
||||
* @return string
|
||||
*/
|
||||
protected function getEncodedValueForProp($propName, $propValue)
|
||||
@@ -210,9 +207,8 @@ class TSProperty
|
||||
/**
|
||||
* Based on the property name in question, get its actual value from the binary blob value.
|
||||
*
|
||||
* @param string $propName
|
||||
* @param string $propValue
|
||||
*
|
||||
* @param string $propName
|
||||
* @param string $propValue
|
||||
* @return string|int
|
||||
*/
|
||||
protected function getDecodedValueForProp($propName, $propValue)
|
||||
@@ -238,9 +234,8 @@ class TSProperty
|
||||
* Decode the property by inspecting the nibbles of each blob, checking
|
||||
* the control, and adding up the results into a final value.
|
||||
*
|
||||
* @param string $hex
|
||||
* @param bool $string Whether or not this is simple string data.
|
||||
*
|
||||
* @param string $hex
|
||||
* @param bool $string Whether or not this is simple string data.
|
||||
* @return string
|
||||
*/
|
||||
protected function decodePropValue($hex, $string = false)
|
||||
@@ -272,9 +267,8 @@ class TSProperty
|
||||
/**
|
||||
* Get the encoded property value as a binary blob.
|
||||
*
|
||||
* @param string $value
|
||||
* @param bool $string
|
||||
*
|
||||
* @param string $value
|
||||
* @param bool $string
|
||||
* @return string
|
||||
*/
|
||||
protected function encodePropValue($value, $string = false)
|
||||
@@ -314,9 +308,8 @@ class TSProperty
|
||||
* a workaround that turns a literal bit-string into a
|
||||
* packed byte-string with 8 bits per byte.
|
||||
*
|
||||
* @param string $bits
|
||||
* @param bool $len
|
||||
*
|
||||
* @param string $bits
|
||||
* @param bool $len
|
||||
* @return string
|
||||
*/
|
||||
protected function packBitString($bits, $len)
|
||||
@@ -337,9 +330,8 @@ class TSProperty
|
||||
/**
|
||||
* Based on the control, adjust the nibble accordingly.
|
||||
*
|
||||
* @param string $nibble
|
||||
* @param string $control
|
||||
*
|
||||
* @param string $nibble
|
||||
* @param string $control
|
||||
* @return string
|
||||
*/
|
||||
protected function nibbleControl($nibble, $control)
|
||||
@@ -362,9 +354,8 @@ class TSProperty
|
||||
* the control for X or Y equals 011010. Additionally, if the dec value of the nibble is > 9, then the nibble value
|
||||
* must be subtracted by 9 before the final value is constructed.
|
||||
*
|
||||
* @param string $nibbleType Either X or Y
|
||||
* @param string $nibble
|
||||
*
|
||||
* @param string $nibbleType Either X or Y
|
||||
* @param string $nibble
|
||||
* @return string
|
||||
*/
|
||||
protected function getNibbleWithControl($nibbleType, $nibble)
|
||||
@@ -384,9 +375,8 @@ class TSProperty
|
||||
/**
|
||||
* Need to make sure hex values are always an even length, so pad as needed.
|
||||
*
|
||||
* @param int $int
|
||||
* @param int $padLength The hex string must be padded to this length (with zeros).
|
||||
*
|
||||
* @param int $int
|
||||
* @param int $padLength The hex string must be padded to this length (with zeros).
|
||||
* @return string
|
||||
*/
|
||||
protected function dec2hex($int, $padLength = 2)
|
||||
|
||||
@@ -9,14 +9,14 @@ class TSPropertyArray
|
||||
/**
|
||||
* Represents that the TSPropertyArray data is valid.
|
||||
*/
|
||||
const VALID_SIGNATURE = 'P';
|
||||
public const VALID_SIGNATURE = 'P';
|
||||
|
||||
/**
|
||||
* The default values for the TSPropertyArray structure.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
const DEFAULTS = [
|
||||
public const DEFAULTS = [
|
||||
'CtxCfgPresent' => 2953518677,
|
||||
'CtxWFProfilePath' => '',
|
||||
'CtxWFProfilePathW' => '',
|
||||
@@ -71,7 +71,7 @@ class TSPropertyArray
|
||||
* - Pass the userParameters binary value. The object representation of that will be decoded and constructed.
|
||||
* - Pass nothing and a default set of TSProperty key => value pairs will be used (See DEFAULTS constant).
|
||||
*
|
||||
* @param mixed $tsPropertyArray
|
||||
* @param mixed $tsPropertyArray
|
||||
*/
|
||||
public function __construct($tsPropertyArray = null)
|
||||
{
|
||||
@@ -93,8 +93,7 @@ class TSPropertyArray
|
||||
/**
|
||||
* Check if a specific TSProperty exists by its property name.
|
||||
*
|
||||
* @param string $propName
|
||||
*
|
||||
* @param string $propName
|
||||
* @return bool
|
||||
*/
|
||||
public function has($propName)
|
||||
@@ -105,8 +104,7 @@ class TSPropertyArray
|
||||
/**
|
||||
* Get a TSProperty object by its property name (ie. CtxWFProfilePath).
|
||||
*
|
||||
* @param string $propName
|
||||
*
|
||||
* @param string $propName
|
||||
* @return TSProperty
|
||||
*/
|
||||
public function get($propName)
|
||||
@@ -119,8 +117,7 @@ class TSPropertyArray
|
||||
/**
|
||||
* Add a TSProperty object. If it already exists, it will be overwritten.
|
||||
*
|
||||
* @param TSProperty $tsProperty
|
||||
*
|
||||
* @param TSProperty $tsProperty
|
||||
* @return $this
|
||||
*/
|
||||
public function add(TSProperty $tsProperty)
|
||||
@@ -133,8 +130,7 @@ class TSPropertyArray
|
||||
/**
|
||||
* Remove a TSProperty by its property name (ie. CtxMinEncryptionLevel).
|
||||
*
|
||||
* @param string $propName
|
||||
*
|
||||
* @param string $propName
|
||||
* @return $this
|
||||
*/
|
||||
public function remove($propName)
|
||||
@@ -151,9 +147,8 @@ class TSPropertyArray
|
||||
/**
|
||||
* Set the value for a specific TSProperty by its name.
|
||||
*
|
||||
* @param string $propName
|
||||
* @param mixed $propValue
|
||||
*
|
||||
* @param string $propName
|
||||
* @param mixed $propValue
|
||||
* @return $this
|
||||
*/
|
||||
public function set($propName, $propValue)
|
||||
@@ -214,7 +209,7 @@ class TSPropertyArray
|
||||
/**
|
||||
* Validates that the given property name exists.
|
||||
*
|
||||
* @param string $propName
|
||||
* @param string $propName
|
||||
*/
|
||||
protected function validateProp($propName)
|
||||
{
|
||||
@@ -224,8 +219,7 @@ class TSPropertyArray
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $propName
|
||||
*
|
||||
* @param string $propName
|
||||
* @return TSProperty
|
||||
*/
|
||||
protected function getTsPropObj($propName)
|
||||
@@ -236,8 +230,7 @@ class TSPropertyArray
|
||||
/**
|
||||
* Get an associative array with all of the userParameters property names and values.
|
||||
*
|
||||
* @param string $userParameters
|
||||
*
|
||||
* @param string $userParameters
|
||||
* @return void
|
||||
*/
|
||||
protected function decodeUserParameters($userParameters)
|
||||
@@ -260,7 +253,7 @@ class TSPropertyArray
|
||||
// Reserved data length + (count and sig length == 4) + the added lengths of the TSPropertyArray
|
||||
// This saves anything after that variable TSPropertyArray data, so as to not squash anything stored there
|
||||
if (strlen($userParameters) > (96 + 4 + $length)) {
|
||||
$this->postBinary = hex2bin(substr($userParameters, (96 + 4 + $length)));
|
||||
$this->postBinary = hex2bin(substr($userParameters, 96 + 4 + $length));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,9 +263,8 @@ class TSPropertyArray
|
||||
* individual TSProperty structures. Return the full length
|
||||
* of the TSPropertyArray data.
|
||||
*
|
||||
* @param string $tsPropertyArray
|
||||
* @param int $tsPropCount
|
||||
*
|
||||
* @param string $tsPropertyArray
|
||||
* @param int $tsPropCount
|
||||
* @return int The length of the data in the TSPropertyArray
|
||||
*/
|
||||
protected function addTSPropData($tsPropertyArray, $tsPropCount)
|
||||
|
||||
@@ -5,11 +5,14 @@ namespace LdapRecord\Models\Attributes;
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonInterface;
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Utilities;
|
||||
|
||||
class Timestamp
|
||||
{
|
||||
public const WINDOWS_INT_MAX = 9223372036854775807;
|
||||
|
||||
/**
|
||||
* The current timestamp type.
|
||||
*
|
||||
@@ -31,7 +34,7 @@ class Timestamp
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $type
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
*/
|
||||
@@ -43,7 +46,7 @@ class Timestamp
|
||||
/**
|
||||
* Set the type of timestamp to convert from / to.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $type
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
*/
|
||||
@@ -59,8 +62,7 @@ class Timestamp
|
||||
/**
|
||||
* Converts the value to an LDAP date string.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return float|string
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -107,21 +109,19 @@ class Timestamp
|
||||
/**
|
||||
* Determine if the value given is in Windows Integer (NTFS Filetime) format.
|
||||
*
|
||||
* @param int|string $value
|
||||
*
|
||||
* @param int|string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function valueIsWindowsIntegerType($value)
|
||||
{
|
||||
return is_numeric($value) && strlen((string) $value) === 18;
|
||||
return is_numeric($value) && in_array(strlen((string) $value), [18, 19]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the LDAP timestamp value to a Carbon instance.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return Carbon|false
|
||||
* @param mixed $value
|
||||
* @return Carbon|int|false
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
*/
|
||||
@@ -153,14 +153,13 @@ class Timestamp
|
||||
/**
|
||||
* Converts standard LDAP timestamps to a date time object.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return DateTime|false
|
||||
*/
|
||||
protected function convertLdapTimeToDateTime($value)
|
||||
{
|
||||
return DateTime::createFromFormat(
|
||||
strpos($value, 'Z') !== false ? 'YmdHis\Z' : 'YmdHisT',
|
||||
str_contains((string) $value, 'Z') ? 'YmdHis\Z' : 'YmdHisT',
|
||||
$value
|
||||
);
|
||||
}
|
||||
@@ -168,8 +167,7 @@ class Timestamp
|
||||
/**
|
||||
* Converts date objects to a standard LDAP timestamp.
|
||||
*
|
||||
* @param DateTime $date
|
||||
*
|
||||
* @param DateTime $date
|
||||
* @return string
|
||||
*/
|
||||
protected function convertDateTimeToLdapTime(DateTime $date)
|
||||
@@ -182,23 +180,22 @@ class Timestamp
|
||||
/**
|
||||
* Converts standard windows timestamps to a date time object.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return DateTime|false
|
||||
*/
|
||||
protected function convertWindowsTimeToDateTime($value)
|
||||
{
|
||||
return DateTime::createFromFormat(
|
||||
strpos($value, '0Z') !== false ? 'YmdHis.0\Z' : 'YmdHis.0T',
|
||||
$value
|
||||
str_contains((string) $value, '0Z') ? 'YmdHis.0\Z' : 'YmdHis.0T',
|
||||
$value,
|
||||
new DateTimeZone('UTC')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts date objects to a windows timestamp.
|
||||
*
|
||||
* @param DateTime $date
|
||||
*
|
||||
* @param DateTime $date
|
||||
* @return string
|
||||
*/
|
||||
protected function convertDateTimeToWindows(DateTime $date)
|
||||
@@ -211,20 +208,25 @@ class Timestamp
|
||||
/**
|
||||
* Converts standard windows integer dates to a date time object.
|
||||
*
|
||||
* @param int $value
|
||||
*
|
||||
* @return DateTime|false
|
||||
* @param int $value
|
||||
* @return DateTime|int|false
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function convertWindowsIntegerTimeToDateTime($value)
|
||||
{
|
||||
// ActiveDirectory dates that contain integers may return
|
||||
// "0" when they are not set. We will validate that here.
|
||||
if (! $value) {
|
||||
if (is_null($value) || $value === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($value == 0) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
if ($value == static::WINDOWS_INT_MAX) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
return (new DateTime())->setTimestamp(
|
||||
Utilities::convertWindowsTimeToUnixTime($value)
|
||||
);
|
||||
@@ -233,8 +235,7 @@ class Timestamp
|
||||
/**
|
||||
* Converts date objects to a windows integer timestamp.
|
||||
*
|
||||
* @param DateTime $date
|
||||
*
|
||||
* @param DateTime $date
|
||||
* @return float
|
||||
*/
|
||||
protected function convertDateTimeToWindowsInteger(DateTime $date)
|
||||
|
||||
@@ -11,9 +11,9 @@ class BatchModification
|
||||
/**
|
||||
* The array keys to be used in batch modifications.
|
||||
*/
|
||||
const KEY_ATTRIB = 'attrib';
|
||||
const KEY_MODTYPE = 'modtype';
|
||||
const KEY_VALUES = 'values';
|
||||
public const KEY_ATTRIB = 'attrib';
|
||||
public const KEY_MODTYPE = 'modtype';
|
||||
public const KEY_VALUES = 'values';
|
||||
|
||||
/**
|
||||
* The attribute of the modification.
|
||||
@@ -46,9 +46,9 @@ class BatchModification
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|null $attribute
|
||||
* @param string|int|null $type
|
||||
* @param array $values
|
||||
* @param string|null $attribute
|
||||
* @param string|int|null $type
|
||||
* @param array $values
|
||||
*/
|
||||
public function __construct($attribute = null, $type = null, array $values = [])
|
||||
{
|
||||
@@ -60,8 +60,7 @@ class BatchModification
|
||||
/**
|
||||
* Set the original value of the attribute before modification.
|
||||
*
|
||||
* @param array|string $original
|
||||
*
|
||||
* @param array|string $original
|
||||
* @return $this
|
||||
*/
|
||||
public function setOriginal($original = [])
|
||||
@@ -84,8 +83,7 @@ class BatchModification
|
||||
/**
|
||||
* Set the attribute of the modification.
|
||||
*
|
||||
* @param string $attribute
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute($attribute)
|
||||
@@ -108,8 +106,7 @@ class BatchModification
|
||||
/**
|
||||
* Set the values of the modification.
|
||||
*
|
||||
* @param array $values
|
||||
*
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function setValues(array $values = [])
|
||||
@@ -127,8 +124,7 @@ class BatchModification
|
||||
/**
|
||||
* Normalize all of the attribute values.
|
||||
*
|
||||
* @param array|string $values
|
||||
*
|
||||
* @param array|string $values
|
||||
* @return array
|
||||
*/
|
||||
protected function normalizeAttributeValues($values = [])
|
||||
@@ -152,8 +148,7 @@ class BatchModification
|
||||
/**
|
||||
* Set the type of the modification.
|
||||
*
|
||||
* @param int|null $type
|
||||
*
|
||||
* @param int|null $type
|
||||
* @return $this
|
||||
*/
|
||||
public function setType($type = null)
|
||||
@@ -207,7 +202,7 @@ class BatchModification
|
||||
case empty($this->original) && ! empty($this->values):
|
||||
return $this->setType(LDAP_MODIFY_BATCH_ADD);
|
||||
default:
|
||||
return $this->determineBatchTypeFromOriginal();
|
||||
return $this->determineBatchTypeFromOriginal();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,8 +286,7 @@ class BatchModification
|
||||
/**
|
||||
* Determines if the given modtype is valid.
|
||||
*
|
||||
* @param int $type
|
||||
*
|
||||
* @param int $type
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidType($type)
|
||||
|
||||
@@ -9,11 +9,22 @@ use LdapRecord\Support\Arr;
|
||||
|
||||
class Collection extends QueryCollection
|
||||
{
|
||||
/**
|
||||
* Get a collection of the model's distinguished names.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function modelDns()
|
||||
{
|
||||
return $this->map(function (Model $model) {
|
||||
return $model->getDn();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the collection contains all of the given models, or any models.
|
||||
*
|
||||
* @param mixed $models
|
||||
*
|
||||
* @param mixed $models
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($models = null)
|
||||
@@ -47,10 +58,9 @@ class Collection extends QueryCollection
|
||||
/**
|
||||
* Determine if any of the given models are contained in the collection.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $operator
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($key, $operator = null, $value = null)
|
||||
@@ -78,8 +88,7 @@ class Collection extends QueryCollection
|
||||
/**
|
||||
* Get the provided models as an array.
|
||||
*
|
||||
* @param mixed $models
|
||||
*
|
||||
* @param mixed $models
|
||||
* @return array
|
||||
*/
|
||||
protected function getArrayableModels($models = null)
|
||||
@@ -92,17 +101,16 @@ class Collection extends QueryCollection
|
||||
/**
|
||||
* Compare the related model with the given.
|
||||
*
|
||||
* @param Model|string $model
|
||||
* @param Model $related
|
||||
*
|
||||
* @param Model|string $model
|
||||
* @param Model $related
|
||||
* @return bool
|
||||
*/
|
||||
protected function compareModelWithRelated($model, $related)
|
||||
{
|
||||
if (is_string($model)) {
|
||||
return $this->isValidDn($model)
|
||||
? $related->getDn() == $model
|
||||
: $related->getName() == $model;
|
||||
? strcasecmp($related->getDn(), $model) === 0
|
||||
: strcasecmp($related->getName(), $model) === 0;
|
||||
}
|
||||
|
||||
return $related->is($model);
|
||||
@@ -111,8 +119,7 @@ class Collection extends QueryCollection
|
||||
/**
|
||||
* Determine if the given string is a valid distinguished name.
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @param string $dn
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidDn($dn)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace LdapRecord\Models\Concerns;
|
||||
|
||||
/** @mixin \LdapRecord\Models\Model */
|
||||
trait CanAuthenticate
|
||||
{
|
||||
/**
|
||||
@@ -17,7 +18,7 @@ trait CanAuthenticate
|
||||
/**
|
||||
* Get the unique identifier for the user.
|
||||
*
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthIdentifier()
|
||||
{
|
||||
@@ -47,8 +48,7 @@ trait CanAuthenticate
|
||||
/**
|
||||
* Set the token value for the "remember me" session.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @param string $value
|
||||
* @return void
|
||||
*/
|
||||
public function setRememberToken($value)
|
||||
|
||||
@@ -74,6 +74,18 @@ trait HasAttributes
|
||||
*/
|
||||
protected static $mutatorCache = [];
|
||||
|
||||
/**
|
||||
* Convert the model's original attributes to an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function originalToArray()
|
||||
{
|
||||
return $this->encodeAttributes(
|
||||
$this->convertAttributesForJson($this->original)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the model's attributes to an array.
|
||||
*
|
||||
@@ -111,11 +123,38 @@ trait HasAttributes
|
||||
return $this->encodeAttributes($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the model's serialized original attributes to their original form.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
public function arrayToOriginal(array $attributes)
|
||||
{
|
||||
return $this->decodeAttributes(
|
||||
$this->convertAttributesFromJson($attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the model's serialized attributes to their original form.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
public function arrayToAttributes(array $attributes)
|
||||
{
|
||||
$attributes = $this->restoreDateAttributesFromArray($attributes);
|
||||
|
||||
return $this->decodeAttributes(
|
||||
$this->convertAttributesFromJson($attributes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the date attributes to the attributes array.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function addDateAttributesToArray(array $attributes)
|
||||
@@ -135,11 +174,31 @@ trait HasAttributes
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the date attributes to their true value from serialized attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function restoreDateAttributesFromArray(array $attributes)
|
||||
{
|
||||
foreach ($this->getDates() as $attribute => $type) {
|
||||
if (! isset($attributes[$attribute])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$date = $this->fromDateTime($type, $attributes[$attribute]);
|
||||
|
||||
$attributes[$attribute] = Arr::wrap($date);
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a date for array / JSON serialization.
|
||||
*
|
||||
* @param DateTimeInterface $date
|
||||
*
|
||||
* @param DateTimeInterface $date
|
||||
* @return string
|
||||
*/
|
||||
protected function serializeDate(DateTimeInterface $date)
|
||||
@@ -162,10 +221,24 @@ trait HasAttributes
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the given value for proper serialization.
|
||||
* Recursively UTF-8 decode the given attributes.
|
||||
*
|
||||
* @param string $value
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
public function decodeAttributes($attributes)
|
||||
{
|
||||
array_walk_recursive($attributes, function (&$value) {
|
||||
$value = $this->decodeValue($value);
|
||||
});
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the value for serialization.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function encodeValue($value)
|
||||
@@ -173,15 +246,33 @@ trait HasAttributes
|
||||
// If we are able to detect the encoding, we will
|
||||
// encode only the attributes that need to be,
|
||||
// so that we do not double encode values.
|
||||
return MbString::isLoaded() && MbString::isUtf8($value) ? $value : utf8_encode($value);
|
||||
if (MbString::isLoaded() && MbString::isUtf8($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return utf8_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the value from serialization.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function decodeValue($value)
|
||||
{
|
||||
if (MbString::isLoaded() && MbString::isUtf8($value)) {
|
||||
return mb_convert_encoding($value, 'UTF-8', 'ISO-8859-1');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the mutated attributes to the attributes array.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $mutatedAttributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $mutatedAttributes
|
||||
* @return array
|
||||
*/
|
||||
protected function addMutatedAttributesToArray(array $attributes, array $mutatedAttributes)
|
||||
@@ -221,8 +312,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Fills the entry with the supplied attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function fill(array $attributes = [])
|
||||
@@ -237,9 +327,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Returns the models attribute by its key.
|
||||
*
|
||||
* @param int|string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @param int|string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute($key, $default = null)
|
||||
@@ -254,9 +343,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Get an attributes value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttributeValue($key, $default = null)
|
||||
@@ -282,8 +370,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the given attribute is a date.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isDateAttribute($key)
|
||||
@@ -310,9 +397,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Convert the given date value to an LDAP compatible value.
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
* @return float|string
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -325,9 +411,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Convert the given LDAP date value to a Carbon instance.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $type
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $type
|
||||
* @return Carbon|false
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -340,9 +425,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine whether an attribute should be cast to a native type.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $types
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|string|null $types
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCast($key, $types = null)
|
||||
@@ -367,8 +451,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine whether a value is JSON castable for inbound manipulation.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
protected function isJsonCastable($key)
|
||||
@@ -379,8 +462,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Get the type of cast for a model attribute.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
protected function getCastType($key)
|
||||
@@ -399,8 +481,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the cast is a decimal.
|
||||
*
|
||||
* @param string $cast
|
||||
*
|
||||
* @param string $cast
|
||||
* @return bool
|
||||
*/
|
||||
protected function isDecimalCast($cast)
|
||||
@@ -411,8 +492,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the cast is a datetime.
|
||||
*
|
||||
* @param string $cast
|
||||
*
|
||||
* @param string $cast
|
||||
* @return bool
|
||||
*/
|
||||
protected function isDateTimeCast($cast)
|
||||
@@ -423,8 +503,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the given attribute must be casted.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
protected function isCastedAttribute($key)
|
||||
@@ -435,9 +514,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Cast an attribute to a native PHP type.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|null $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param array|null $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function castAttribute($key, $value)
|
||||
@@ -490,9 +568,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Cast the given attribute to JSON.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function castAttributeAsJson($key, $value)
|
||||
@@ -522,8 +599,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Encode the given value as JSON.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
protected function asJson($value)
|
||||
@@ -534,9 +610,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Decode the given JSON back into an array or object.
|
||||
*
|
||||
* @param string $value
|
||||
* @param bool $asObject
|
||||
*
|
||||
* @param string $value
|
||||
* @param bool $asObject
|
||||
* @return mixed
|
||||
*/
|
||||
public function fromJson($value, $asObject = false)
|
||||
@@ -547,8 +622,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Decode the given float.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function fromFloat($value)
|
||||
@@ -568,8 +642,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Cast the value to a boolean.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function asBoolean($value)
|
||||
@@ -582,9 +655,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Cast a decimal value as a string.
|
||||
*
|
||||
* @param float $value
|
||||
* @param int $decimals
|
||||
*
|
||||
* @param float $value
|
||||
* @param int $decimals
|
||||
* @return string
|
||||
*/
|
||||
protected function asDecimal($value, $decimals)
|
||||
@@ -605,8 +677,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Get an attribute array of all arrayable values.
|
||||
*
|
||||
* @param array $values
|
||||
*
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
protected function getArrayableItems(array $values)
|
||||
@@ -651,8 +722,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Set the date format used by the model for serialization.
|
||||
*
|
||||
* @param string $format
|
||||
*
|
||||
* @param string $format
|
||||
* @return $this
|
||||
*/
|
||||
public function setDateFormat($format)
|
||||
@@ -665,8 +735,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Get an attribute from the $attributes array.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getAttributeFromArray($key)
|
||||
@@ -687,9 +756,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Returns the first attribute by the specified key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFirstAttribute($key, $default = null)
|
||||
@@ -712,9 +780,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Set an attribute value by the specified key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setAttribute($key, $value)
|
||||
@@ -743,9 +810,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Set an attribute on the model. No checking is done.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setRawAttribute($key, $value)
|
||||
@@ -760,9 +826,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Set the models first attribute value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function setFirstAttribute($key, $value)
|
||||
@@ -773,9 +838,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Add a unique value to the given attribute.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function addAttributeValue($key, $value)
|
||||
@@ -791,8 +855,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if a get mutator exists for an attribute.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function hasGetMutator($key)
|
||||
@@ -803,8 +866,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if a set mutator exists for an attribute.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSetMutator($key)
|
||||
@@ -815,9 +877,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Set the value of an attribute using its mutator.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function setMutatedAttributeValue($key, $value)
|
||||
@@ -828,9 +889,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Get the value of an attribute using its mutator.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getMutatedAttributeValue($key, $value)
|
||||
@@ -843,8 +903,7 @@ trait HasAttributes
|
||||
*
|
||||
* Hyphenated attributes will use pascal cased methods.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getMutatorMethodName($key)
|
||||
@@ -857,9 +916,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Get the value of an attribute using its mutator for array conversion.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
protected function mutateAttributeForArray($key, $value)
|
||||
@@ -874,8 +932,7 @@ trait HasAttributes
|
||||
*
|
||||
* Used when constructing an existing LDAP record.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function setRawAttributes(array $attributes = [])
|
||||
@@ -915,9 +972,8 @@ trait HasAttributes
|
||||
/**
|
||||
* Filters the count key recursively from raw LDAP attributes.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $keys
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
public function filterRawAttributes(array $attributes = [], array $keys = ['count', 'dn'])
|
||||
@@ -938,8 +994,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the model has the given attribute.
|
||||
*
|
||||
* @param int|string $key
|
||||
*
|
||||
* @param int|string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAttribute($key)
|
||||
@@ -991,8 +1046,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the given attribute is dirty.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function isDirty($key)
|
||||
@@ -1013,8 +1067,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Set the accessors to append to model arrays.
|
||||
*
|
||||
* @param array $appends
|
||||
*
|
||||
* @param array $appends
|
||||
* @return $this
|
||||
*/
|
||||
public function setAppends(array $appends)
|
||||
@@ -1027,8 +1080,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Return whether the accessor attribute has been appended.
|
||||
*
|
||||
* @param string $attribute
|
||||
*
|
||||
* @param string $attribute
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAppended($attribute)
|
||||
@@ -1039,8 +1091,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Returns a normalized attribute key.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
public function normalizeAttributeKey($key)
|
||||
@@ -1056,8 +1107,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Determine if the new and old values for a given key are equivalent.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
protected function originalIsEquivalent($key)
|
||||
@@ -1097,8 +1147,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Extract and cache all the mutated attributes of a class.
|
||||
*
|
||||
* @param string $class
|
||||
*
|
||||
* @param string $class
|
||||
* @return void
|
||||
*/
|
||||
public static function cacheMutatedAttributes($class)
|
||||
@@ -1113,8 +1162,7 @@ trait HasAttributes
|
||||
/**
|
||||
* Get all of the attribute mutator methods.
|
||||
*
|
||||
* @param mixed $class
|
||||
*
|
||||
* @param mixed $class
|
||||
* @return array
|
||||
*/
|
||||
protected static function getMutatorMethods($class)
|
||||
|
||||
@@ -4,15 +4,17 @@ namespace LdapRecord\Models\Concerns;
|
||||
|
||||
use Closure;
|
||||
use LdapRecord\Events\NullDispatcher;
|
||||
use LdapRecord\Models\Events;
|
||||
use LdapRecord\Models\Events\Event;
|
||||
use LdapRecord\Support\Arr;
|
||||
|
||||
/** @mixin \LdapRecord\Models\Model */
|
||||
trait HasEvents
|
||||
{
|
||||
/**
|
||||
* Execute the callback without raising any events.
|
||||
*
|
||||
* @param Closure $callback
|
||||
*
|
||||
* @param Closure $callback
|
||||
* @return mixed
|
||||
*/
|
||||
protected static function withoutEvents(Closure $callback)
|
||||
@@ -37,10 +39,37 @@ trait HasEvents
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires the specified model event.
|
||||
* Dispatch the given model events.
|
||||
*
|
||||
* @param Event $event
|
||||
* @param string|array $events
|
||||
* @param array $args
|
||||
* @return void
|
||||
*/
|
||||
protected function dispatch($events, array $args = [])
|
||||
{
|
||||
foreach (Arr::wrap($events) as $name) {
|
||||
$this->fireCustomModelEvent($name, $args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire a custom model event.
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
*/
|
||||
protected function fireCustomModelEvent($name, array $args = [])
|
||||
{
|
||||
$event = implode('\\', [Events::class, ucfirst($name)]);
|
||||
|
||||
return $this->fireModelEvent(new $event($this, ...$args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire a model event.
|
||||
*
|
||||
* @param Event $event
|
||||
* @return mixed
|
||||
*/
|
||||
protected function fireModelEvent(Event $event)
|
||||
@@ -49,11 +78,10 @@ trait HasEvents
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to a model event.
|
||||
*
|
||||
* @param string $event
|
||||
* @param Closure $listener
|
||||
* Listen to a model event.
|
||||
*
|
||||
* @param string $event
|
||||
* @param Closure $listener
|
||||
* @return mixed
|
||||
*/
|
||||
protected function listenForModelEvent($event, Closure $listener)
|
||||
|
||||
@@ -6,14 +6,14 @@ use Closure;
|
||||
use InvalidArgumentException;
|
||||
use LdapRecord\Models\Scope;
|
||||
|
||||
/** @mixin \LdapRecord\Models\Model */
|
||||
trait HasGlobalScopes
|
||||
{
|
||||
/**
|
||||
* Register a new global scope on the model.
|
||||
*
|
||||
* @param Scope|Closure|string $scope
|
||||
* @param Closure|null $implementation
|
||||
*
|
||||
* @param Scope|Closure|string $scope
|
||||
* @param Closure|null $implementation
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
@@ -34,8 +34,7 @@ trait HasGlobalScopes
|
||||
/**
|
||||
* Determine if a model has a global scope.
|
||||
*
|
||||
* @param Scope|string $scope
|
||||
*
|
||||
* @param Scope|string $scope
|
||||
* @return bool
|
||||
*/
|
||||
public static function hasGlobalScope($scope)
|
||||
@@ -46,8 +45,7 @@ trait HasGlobalScopes
|
||||
/**
|
||||
* Get a global scope registered with the model.
|
||||
*
|
||||
* @param Scope|string $scope
|
||||
*
|
||||
* @param Scope|string $scope
|
||||
* @return Scope|Closure|null
|
||||
*/
|
||||
public static function getGlobalScope($scope)
|
||||
|
||||
@@ -6,12 +6,13 @@ use LdapRecord\ConnectionException;
|
||||
use LdapRecord\LdapRecordException;
|
||||
use LdapRecord\Models\Attributes\Password;
|
||||
|
||||
/** @mixin \LdapRecord\Models\Model */
|
||||
trait HasPassword
|
||||
{
|
||||
/**
|
||||
* Set the password on the user.
|
||||
*
|
||||
* @param string|array $password
|
||||
* @param string|array $password
|
||||
*
|
||||
* @throws ConnectionException
|
||||
*/
|
||||
@@ -48,7 +49,7 @@ trait HasPassword
|
||||
/**
|
||||
* Alias for setting the password on the user.
|
||||
*
|
||||
* @param string|array $password
|
||||
* @param string|array $password
|
||||
*
|
||||
* @throws ConnectionException
|
||||
*/
|
||||
@@ -106,10 +107,9 @@ trait HasPassword
|
||||
/**
|
||||
* Set the changed password.
|
||||
*
|
||||
* @param string $oldPassword
|
||||
* @param string $newPassword
|
||||
* @param string $attribute
|
||||
*
|
||||
* @param string $oldPassword
|
||||
* @param string $newPassword
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
protected function setChangedPassword($oldPassword, $newPassword, $attribute)
|
||||
@@ -136,9 +136,8 @@ trait HasPassword
|
||||
/**
|
||||
* Set the password on the model.
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $attribute
|
||||
*
|
||||
* @param string $password
|
||||
* @param string $attribute
|
||||
* @return void
|
||||
*/
|
||||
protected function setPassword($password, $attribute)
|
||||
@@ -155,10 +154,9 @@ trait HasPassword
|
||||
/**
|
||||
* Encode / hash the given password.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $password
|
||||
* @param string $salt
|
||||
* @return string
|
||||
*
|
||||
* @throws LdapRecordException
|
||||
@@ -203,8 +201,7 @@ trait HasPassword
|
||||
/**
|
||||
* Attempt to retrieve the password's salt.
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @param string $method
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPasswordSalt($method)
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace LdapRecord\Models\Concerns;
|
||||
use LdapRecord\Models\Relations\HasMany;
|
||||
use LdapRecord\Models\Relations\HasManyIn;
|
||||
use LdapRecord\Models\Relations\HasOne;
|
||||
use LdapRecord\Models\Relations\Relation;
|
||||
use LdapRecord\Support\Arr;
|
||||
|
||||
trait HasRelationships
|
||||
@@ -12,10 +13,9 @@ trait HasRelationships
|
||||
/**
|
||||
* Returns a new has one relationship.
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
* @return HasOne
|
||||
*/
|
||||
public function hasOne($related, $relationKey, $foreignKey = 'dn')
|
||||
@@ -26,10 +26,9 @@ trait HasRelationships
|
||||
/**
|
||||
* Returns a new has many relationship.
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
* @return HasMany
|
||||
*/
|
||||
public function hasMany($related, $relationKey, $foreignKey = 'dn')
|
||||
@@ -40,10 +39,9 @@ trait HasRelationships
|
||||
/**
|
||||
* Returns a new has many in relationship.
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
*
|
||||
* @param mixed $related
|
||||
* @param string $relationKey
|
||||
* @param string $foreignKey
|
||||
* @return HasManyIn
|
||||
*/
|
||||
public function hasManyIn($related, $relationKey, $foreignKey = 'dn')
|
||||
@@ -51,6 +49,29 @@ trait HasRelationships
|
||||
return new HasManyIn($this->newQuery(), $this, $related, $relationKey, $foreignKey, $this->guessRelationshipName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a relationship by its name.
|
||||
*
|
||||
* @param string $relationName
|
||||
* @return Relation|null
|
||||
*/
|
||||
public function getRelation($relationName)
|
||||
{
|
||||
if (! method_exists($this, $relationName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $relation = $this->{$relationName}()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $relation instanceof Relation) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $relation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relationships name.
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace LdapRecord\Models\Concerns;
|
||||
|
||||
/** @mixin \LdapRecord\Models\Model */
|
||||
trait HasScopes
|
||||
{
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace LdapRecord\Models\Concerns;
|
||||
* @author Taylor Otwell
|
||||
*
|
||||
* @see https://laravel.com
|
||||
*
|
||||
* @mixin \LdapRecord\Models\Model
|
||||
*/
|
||||
trait HidesAttributes
|
||||
{
|
||||
@@ -38,8 +40,7 @@ trait HidesAttributes
|
||||
/**
|
||||
* Set the hidden attributes for the model.
|
||||
*
|
||||
* @param array $hidden
|
||||
*
|
||||
* @param array $hidden
|
||||
* @return $this
|
||||
*/
|
||||
public function setHidden(array $hidden)
|
||||
@@ -52,8 +53,7 @@ trait HidesAttributes
|
||||
/**
|
||||
* Add hidden attributes for the model.
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function addHidden($attributes = null)
|
||||
@@ -79,8 +79,7 @@ trait HidesAttributes
|
||||
/**
|
||||
* Set the visible attributes for the model.
|
||||
*
|
||||
* @param array $visible
|
||||
*
|
||||
* @param array $visible
|
||||
* @return $this
|
||||
*/
|
||||
public function setVisible(array $visible)
|
||||
@@ -93,8 +92,7 @@ trait HidesAttributes
|
||||
/**
|
||||
* Add visible attributes for the model.
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
*
|
||||
* @param array|string|null $attributes
|
||||
* @return void
|
||||
*/
|
||||
public function addVisible($attributes = null)
|
||||
@@ -108,8 +106,7 @@ trait HidesAttributes
|
||||
/**
|
||||
* Make the given, typically hidden, attributes visible.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeVisible($attributes)
|
||||
@@ -126,8 +123,7 @@ trait HidesAttributes
|
||||
/**
|
||||
* Make the given, typically visible, attributes hidden.
|
||||
*
|
||||
* @param array|string $attributes
|
||||
*
|
||||
* @param array|string $attributes
|
||||
* @return $this
|
||||
*/
|
||||
public function makeHidden($attributes)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace LdapRecord\Models\Concerns;
|
||||
|
||||
/** @mixin HasAttributes */
|
||||
trait SerializesAndRestoresPropertyValues
|
||||
{
|
||||
/**
|
||||
* Get the property value prepared for serialization.
|
||||
*
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getSerializedPropertyValue($property, $value)
|
||||
{
|
||||
if ($property === 'original') {
|
||||
return $this->originalToArray();
|
||||
}
|
||||
|
||||
if ($property === 'attributes') {
|
||||
return $this->attributesToArray();
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unserialized property value after deserialization.
|
||||
*
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getUnserializedPropertyValue($property, $value)
|
||||
{
|
||||
if ($property === 'original') {
|
||||
return $this->arrayToOriginal($value);
|
||||
}
|
||||
|
||||
if ($property === 'attributes') {
|
||||
return $this->arrayToAttributes($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
143
data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/SerializesProperties.php
vendored
Normal file
143
data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/SerializesProperties.php
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace LdapRecord\Models\Concerns;
|
||||
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
|
||||
trait SerializesProperties
|
||||
{
|
||||
use SerializesAndRestoresPropertyValues;
|
||||
|
||||
/**
|
||||
* Prepare the attributes for serialization.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
$properties = (new ReflectionClass($this))->getProperties();
|
||||
|
||||
foreach ($properties as $property) {
|
||||
$property->setValue($this, $this->getSerializedPropertyValue(
|
||||
$property->getName(),
|
||||
$this->getPropertyValue($property)
|
||||
));
|
||||
}
|
||||
|
||||
return array_values(array_filter(array_map(function ($p) {
|
||||
return $p->isStatic() ? null : $p->getName();
|
||||
}, $properties)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the attributes after serialization.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
foreach ((new ReflectionClass($this))->getProperties() as $property) {
|
||||
if ($property->isStatic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setValue($this, $this->getUnserializedPropertyValue(
|
||||
$property->getName(),
|
||||
$this->getPropertyValue($property)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the model for serialization.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __serialize()
|
||||
{
|
||||
$values = [];
|
||||
|
||||
$properties = (new ReflectionClass($this))->getProperties();
|
||||
|
||||
$class = get_class($this);
|
||||
|
||||
foreach ($properties as $property) {
|
||||
if ($property->isStatic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
if (! $property->isInitialized($this)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $property->getName();
|
||||
|
||||
if ($property->isPrivate()) {
|
||||
$name = "\0{$class}\0{$name}";
|
||||
} elseif ($property->isProtected()) {
|
||||
$name = "\0*\0{$name}";
|
||||
}
|
||||
|
||||
$values[$name] = $this->getSerializedPropertyValue(
|
||||
$property->getName(),
|
||||
$this->getPropertyValue($property)
|
||||
);
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the model after serialization.
|
||||
*
|
||||
* @param array $values
|
||||
* @return void
|
||||
*/
|
||||
public function __unserialize(array $values)
|
||||
{
|
||||
$properties = (new ReflectionClass($this))->getProperties();
|
||||
|
||||
$class = get_class($this);
|
||||
|
||||
foreach ($properties as $property) {
|
||||
if ($property->isStatic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $property->getName();
|
||||
|
||||
if ($property->isPrivate()) {
|
||||
$name = "\0{$class}\0{$name}";
|
||||
} elseif ($property->isProtected()) {
|
||||
$name = "\0*\0{$name}";
|
||||
}
|
||||
|
||||
if (! array_key_exists($name, $values)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$property->setAccessible(true);
|
||||
|
||||
$property->setValue(
|
||||
$this,
|
||||
$this->getUnserializedPropertyValue($property->getName(), $values[$name])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the property value for the given property.
|
||||
*
|
||||
* @param ReflectionProperty $property
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getPropertyValue(ReflectionProperty $property)
|
||||
{
|
||||
$property->setAccessible(true);
|
||||
|
||||
return $property->getValue($this);
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,7 @@ trait DetectsResetIntegers
|
||||
* LDAP attributes to instruct the server to reset the
|
||||
* value to an 'unset' or 'cleared' state.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function valueIsResetInteger($value)
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
namespace LdapRecord\Models\DirectoryServer;
|
||||
|
||||
use LdapRecord\Models\Model;
|
||||
use LdapRecord\Models\Types\DirectoryServer;
|
||||
|
||||
class Entry extends Model
|
||||
class Entry extends Model implements DirectoryServer
|
||||
{
|
||||
/**
|
||||
* The attribute key that contains the models object GUID.
|
||||
|
||||
@@ -16,7 +16,7 @@ abstract class Event
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param Model $model
|
||||
*/
|
||||
public function __construct(Model $model)
|
||||
{
|
||||
|
||||
@@ -23,9 +23,9 @@ class Renaming extends Event
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param string $rdn
|
||||
* @param string $newParentDn
|
||||
* @param Model $model
|
||||
* @param string $rdn
|
||||
* @param string $newParentDn
|
||||
*/
|
||||
public function __construct(Model $model, $rdn, $newParentDn)
|
||||
{
|
||||
|
||||
@@ -44,8 +44,7 @@ class Entry extends BaseEntry implements FreeIPA
|
||||
/**
|
||||
* Create a new query builder.
|
||||
*
|
||||
* @param Connection $connection
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @return FreeIpaBuilder
|
||||
*/
|
||||
public function newQueryBuilder(Connection $connection)
|
||||
|
||||
@@ -11,9 +11,8 @@ class AddEntryUuidToSelects implements Scope
|
||||
/**
|
||||
* Add the entry UUID to the selected attributes.
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Builder $query
|
||||
* @param Model $model
|
||||
* @return void
|
||||
*/
|
||||
public function apply(Builder $query, Model $model)
|
||||
|
||||
@@ -11,8 +11,6 @@ use LdapRecord\Container;
|
||||
use LdapRecord\EscapesValues;
|
||||
use LdapRecord\Models\Attributes\DistinguishedName;
|
||||
use LdapRecord\Models\Attributes\Guid;
|
||||
use LdapRecord\Models\Events\Renamed;
|
||||
use LdapRecord\Models\Events\Renaming;
|
||||
use LdapRecord\Query\Model\Builder;
|
||||
use LdapRecord\Support\Arr;
|
||||
use UnexpectedValueException;
|
||||
@@ -27,6 +25,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
use Concerns\HasGlobalScopes;
|
||||
use Concerns\HidesAttributes;
|
||||
use Concerns\HasRelationships;
|
||||
use Concerns\SerializesProperties;
|
||||
|
||||
/**
|
||||
* Indicates if the model exists in the directory.
|
||||
@@ -115,7 +114,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param array $attributes
|
||||
*/
|
||||
public function __construct(array $attributes = [])
|
||||
{
|
||||
@@ -163,9 +162,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Handle dynamic method calls into the model.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, $parameters)
|
||||
@@ -180,9 +178,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Handle dynamic static method calls into the method.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $parameters
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($method, $parameters)
|
||||
@@ -203,8 +200,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Set the models distinguished name.
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @param string $dn
|
||||
* @return $this
|
||||
*/
|
||||
public function setDn($dn)
|
||||
@@ -217,8 +213,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* A mutator for setting the models distinguished name.
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @param string $dn
|
||||
* @return $this
|
||||
*/
|
||||
public function setDnAttribute($dn)
|
||||
@@ -229,8 +224,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* A mutator for setting the models distinguished name.
|
||||
*
|
||||
* @param string $dn
|
||||
*
|
||||
* @param string $dn
|
||||
* @return $this
|
||||
*/
|
||||
public function setDistinguishedNameAttribute($dn)
|
||||
@@ -261,8 +255,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Set the connection associated with the model.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function setConnection($name)
|
||||
@@ -272,11 +265,21 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return static
|
||||
*/
|
||||
public static function make($attributes = [])
|
||||
{
|
||||
return new static($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin querying the model on a given connection.
|
||||
*
|
||||
* @param string|null $connection
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return Builder
|
||||
*/
|
||||
public static function on($connection = null)
|
||||
@@ -291,8 +294,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get all the models from the directory.
|
||||
*
|
||||
* @param array|mixed $attributes
|
||||
*
|
||||
* @param array|mixed $attributes
|
||||
* @return Collection|static[]
|
||||
*/
|
||||
public static function all($attributes = ['*'])
|
||||
@@ -301,15 +303,45 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new model instance.
|
||||
* Get the RootDSE (AD schema) record from the directory.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @param string|null $connection
|
||||
* @return Model
|
||||
*
|
||||
* @return static
|
||||
* @throws \LdapRecord\Models\ModelNotFoundException
|
||||
*/
|
||||
public static function make($attributes = [])
|
||||
public static function getRootDse($connection = null)
|
||||
{
|
||||
return new static($attributes);
|
||||
$model = static::getRootDseModel();
|
||||
|
||||
return $model::on($connection ?? (new $model)->getConnectionName())
|
||||
->in(null)
|
||||
->read()
|
||||
->whereHas('objectclass')
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the root DSE model.
|
||||
*
|
||||
* @return class-string<Model>
|
||||
*/
|
||||
protected static function getRootDseModel()
|
||||
{
|
||||
$instance = (new static);
|
||||
|
||||
switch (true) {
|
||||
case $instance instanceof Types\ActiveDirectory:
|
||||
return ActiveDirectory\Entry::class;
|
||||
case $instance instanceof Types\DirectoryServer:
|
||||
return OpenLDAP\Entry::class;
|
||||
case $instance instanceof Types\OpenLDAP:
|
||||
return OpenLDAP\Entry::class;
|
||||
case $instance instanceof Types\FreeIPA:
|
||||
return FreeIPA\Entry::class;
|
||||
default:
|
||||
return Entry::class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,8 +381,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Create a new query builder.
|
||||
*
|
||||
* @param Connection $connection
|
||||
*
|
||||
* @param Connection $connection
|
||||
* @return Builder
|
||||
*/
|
||||
public function newQueryBuilder(Connection $connection)
|
||||
@@ -361,8 +392,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Create a new model instance.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return static
|
||||
*/
|
||||
public function newInstance(array $attributes = [])
|
||||
@@ -373,8 +403,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Resolve a connection instance.
|
||||
*
|
||||
* @param string|null $connection
|
||||
*
|
||||
* @param string|null $connection
|
||||
* @return Connection
|
||||
*/
|
||||
public static function resolveConnection($connection = null)
|
||||
@@ -405,8 +434,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Set the connection container.
|
||||
*
|
||||
* @param Container $container
|
||||
*
|
||||
* @param Container $container
|
||||
* @return void
|
||||
*/
|
||||
public static function setConnectionContainer(Container $container)
|
||||
@@ -427,8 +455,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Register the query scopes for this builder instance.
|
||||
*
|
||||
* @param Builder $builder
|
||||
*
|
||||
* @param Builder $builder
|
||||
* @return Builder
|
||||
*/
|
||||
public function registerModelScopes($builder)
|
||||
@@ -443,8 +470,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Register the global model scopes.
|
||||
*
|
||||
* @param Builder $builder
|
||||
*
|
||||
* @param Builder $builder
|
||||
* @return Builder
|
||||
*/
|
||||
public function registerGlobalScopes($builder)
|
||||
@@ -459,8 +485,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Apply the model object class scopes to the given builder instance.
|
||||
*
|
||||
* @param Builder $query
|
||||
*
|
||||
* @param Builder $query
|
||||
* @return void
|
||||
*/
|
||||
public function applyObjectClassScopes(Builder $query)
|
||||
@@ -483,10 +508,9 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Returns a new batch modification.
|
||||
*
|
||||
* @param string|null $attribute
|
||||
* @param string|int|null $type
|
||||
* @param array $values
|
||||
*
|
||||
* @param string|null $attribute
|
||||
* @param string|int|null $type
|
||||
* @param array $values
|
||||
* @return BatchModification
|
||||
*/
|
||||
public function newBatchModification($attribute = null, $type = null, $values = [])
|
||||
@@ -497,8 +521,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Returns a new collection with the specified items.
|
||||
*
|
||||
* @param mixed $items
|
||||
*
|
||||
* @param mixed $items
|
||||
* @return Collection
|
||||
*/
|
||||
public function newCollection($items = [])
|
||||
@@ -509,9 +532,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Dynamically retrieve attributes on the object.
|
||||
*
|
||||
* @param mixed $key
|
||||
*
|
||||
* @return bool
|
||||
* @param string $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($key)
|
||||
{
|
||||
@@ -521,9 +543,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Dynamically set attributes on the object.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function __set($key, $value)
|
||||
@@ -534,8 +555,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if the given offset exists.
|
||||
*
|
||||
* @param string $offset
|
||||
*
|
||||
* @param string $offset
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
@@ -547,8 +567,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get the value for a given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
*
|
||||
* @param string $offset
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
@@ -560,9 +579,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Set the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
* @param mixed $value
|
||||
*
|
||||
* @param string $offset
|
||||
* @param mixed $value
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
@@ -574,8 +592,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Unset the value at the given offset.
|
||||
*
|
||||
* @param string $offset
|
||||
*
|
||||
* @param string $offset
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
@@ -587,8 +604,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if an attribute exists on the model.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($key)
|
||||
@@ -599,8 +615,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Unset an attribute on the model.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*/
|
||||
public function __unset($key)
|
||||
@@ -630,26 +645,36 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts extra attributes for JSON serialization.
|
||||
*
|
||||
* @param array $attributes
|
||||
* Convert the attributes for JSON serialization.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function convertAttributesForJson(array $attributes = [])
|
||||
{
|
||||
// If the model has a GUID set, we need to convert
|
||||
// it due to it being in binary. Otherwise we'll
|
||||
// receive a JSON serialization exception.
|
||||
if ($this->hasAttribute($this->guidKey)) {
|
||||
return array_replace($attributes, [
|
||||
$this->guidKey => [$this->getConvertedGuid()],
|
||||
]);
|
||||
// If the model has a GUID set, we need to convert it to its
|
||||
// string format, due to it being in binary. Otherwise
|
||||
// we will receive a JSON serialization exception.
|
||||
if (isset($attributes[$this->guidKey])) {
|
||||
$attributes[$this->guidKey] = [$this->getConvertedGuid(
|
||||
Arr::first($attributes[$this->guidKey])
|
||||
)];
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the attributes from JSON serialization.
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function convertAttributesFromJson(array $attributes = [])
|
||||
{
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload a fresh model instance from the directory.
|
||||
*
|
||||
@@ -667,8 +692,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if two models have the same distinguished name and belong to the same connection.
|
||||
*
|
||||
* @param Model|null $model
|
||||
*
|
||||
* @param Model|null $model
|
||||
* @return bool
|
||||
*/
|
||||
public function is($model)
|
||||
@@ -681,8 +705,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if two models are not the same.
|
||||
*
|
||||
* @param Model|null $model
|
||||
*
|
||||
* @param Model|null $model
|
||||
* @return bool
|
||||
*/
|
||||
public function isNot($model)
|
||||
@@ -693,8 +716,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Hydrate a new collection of models from search results.
|
||||
*
|
||||
* @param array $records
|
||||
*
|
||||
* @param array $records
|
||||
* @return Collection
|
||||
*/
|
||||
public function hydrate($records)
|
||||
@@ -709,8 +731,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Converts the current model into the given model.
|
||||
*
|
||||
* @param Model $into
|
||||
*
|
||||
* @param Model $into
|
||||
* @return Model
|
||||
*/
|
||||
public function convert(self $into)
|
||||
@@ -760,8 +781,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Set the models batch modifications.
|
||||
*
|
||||
* @param array $modifications
|
||||
*
|
||||
* @param array $modifications
|
||||
* @return $this
|
||||
*/
|
||||
public function setModifications(array $modifications = [])
|
||||
@@ -778,8 +798,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Adds a batch modification to the model.
|
||||
*
|
||||
* @param array|BatchModification $mod
|
||||
*
|
||||
* @param array|BatchModification $mod
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
@@ -824,8 +843,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get the name of the model, or the given DN.
|
||||
*
|
||||
* @param string|null $dn
|
||||
*
|
||||
* @param string|null $dn
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName($dn = null)
|
||||
@@ -836,8 +854,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get the head attribute of the model, or the given DN.
|
||||
*
|
||||
* @param string|null $dn
|
||||
*
|
||||
* @param string|null $dn
|
||||
* @return string|null
|
||||
*/
|
||||
public function getHead($dn = null)
|
||||
@@ -849,7 +866,6 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
* Get the RDN of the model, of the given DN.
|
||||
*
|
||||
* @param string|null
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getRdn($dn = null)
|
||||
@@ -861,7 +877,6 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
* Get the parent distinguished name of the model, or the given DN.
|
||||
*
|
||||
* @param string|null
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getParentDn($dn = null)
|
||||
@@ -872,8 +887,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Create a new Distinguished Name object.
|
||||
*
|
||||
* @param string|null $dn
|
||||
*
|
||||
* @param string|null $dn
|
||||
* @return DistinguishedName
|
||||
*/
|
||||
public function newDn($dn = null)
|
||||
@@ -910,28 +924,58 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function getObjectClasses()
|
||||
{
|
||||
return $this->getAttribute('objectclass') ?: [];
|
||||
return $this->getAttribute('objectclass', static::$objectClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model's string GUID.
|
||||
*
|
||||
* @param string|null $guid
|
||||
* @return string|null
|
||||
*/
|
||||
public function getConvertedGuid()
|
||||
public function getConvertedGuid($guid = null)
|
||||
{
|
||||
try {
|
||||
return (string) new Guid($this->getObjectGuid());
|
||||
return (string) $this->newObjectGuid(
|
||||
$guid ?? $this->getObjectGuid()
|
||||
);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model's binary GUID.
|
||||
*
|
||||
* @param string|null $guid
|
||||
* @return string|null
|
||||
*/
|
||||
public function getBinaryGuid($guid = null)
|
||||
{
|
||||
try {
|
||||
return $this->newObjectGuid(
|
||||
$guid ?? $this->getObjectGuid()
|
||||
)->getBinary();
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a new object Guid instance.
|
||||
*
|
||||
* @param string $value
|
||||
* @return Guid
|
||||
*/
|
||||
protected function newObjectGuid($value)
|
||||
{
|
||||
return new Guid($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current model is a direct descendant of the given.
|
||||
*
|
||||
* @param static|string $parent
|
||||
*
|
||||
* @param static|string $parent
|
||||
* @return bool
|
||||
*/
|
||||
public function isChildOf($parent)
|
||||
@@ -944,8 +988,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if the current model is a direct ascendant of the given.
|
||||
*
|
||||
* @param static|string $child
|
||||
*
|
||||
* @param static|string $child
|
||||
* @return bool
|
||||
*/
|
||||
public function isParentOf($child)
|
||||
@@ -958,8 +1001,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if the current model is a descendant of the given.
|
||||
*
|
||||
* @param static|string $model
|
||||
*
|
||||
* @param static|string $model
|
||||
* @return bool
|
||||
*/
|
||||
public function isDescendantOf($model)
|
||||
@@ -970,8 +1012,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determine if the current model is a ancestor of the given.
|
||||
*
|
||||
* @param static|string $model
|
||||
*
|
||||
* @param static|string $model
|
||||
* @return bool
|
||||
*/
|
||||
public function isAncestorOf($model)
|
||||
@@ -982,9 +1023,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determines if the DN is inside of the parent DN.
|
||||
*
|
||||
* @param static|string $dn
|
||||
* @param static|string $parentDn
|
||||
*
|
||||
* @param static|string $dn
|
||||
* @param static|string $parentDn
|
||||
* @return bool
|
||||
*/
|
||||
protected function dnIsInside($dn, $parentDn)
|
||||
@@ -997,8 +1037,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Set the base DN of where the model should be created in.
|
||||
*
|
||||
* @param static|string $dn
|
||||
*
|
||||
* @param static|string $dn
|
||||
* @return $this
|
||||
*/
|
||||
public function inside($dn)
|
||||
@@ -1011,8 +1050,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Save the model to the directory without raising any events.
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @param array $attributes
|
||||
* @return void
|
||||
*
|
||||
* @throws \LdapRecord\LdapRecordException
|
||||
@@ -1027,8 +1065,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Save the model to the directory.
|
||||
*
|
||||
* @param array $attributes The attributes to update or create for the current entry.
|
||||
*
|
||||
* @param array $attributes The attributes to update or create for the current entry.
|
||||
* @return void
|
||||
*
|
||||
* @throws \LdapRecord\LdapRecordException
|
||||
@@ -1037,11 +1074,13 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
{
|
||||
$this->fill($attributes);
|
||||
|
||||
$this->fireModelEvent(new Events\Saving($this));
|
||||
$this->dispatch('saving');
|
||||
|
||||
$this->exists ? $this->performUpdate() : $this->performInsert();
|
||||
|
||||
$this->fireModelEvent(new Events\Saved($this));
|
||||
$this->dispatch('saved');
|
||||
|
||||
$this->modifications = [];
|
||||
|
||||
$this->in = null;
|
||||
}
|
||||
@@ -1071,7 +1110,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
$this->setDn($this->getCreatableDn());
|
||||
}
|
||||
|
||||
$this->fireModelEvent(new Events\Creating($this));
|
||||
$this->dispatch('creating');
|
||||
|
||||
// Here we perform the insert of new object in the directory,
|
||||
// but filter out any empty attributes before sending them
|
||||
@@ -1079,7 +1118,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
// attributes have been given empty or null values.
|
||||
$query->insert($this->getDn(), array_filter($this->getAttributes()));
|
||||
|
||||
$this->fireModelEvent(new Events\Created($this));
|
||||
$this->dispatch('created');
|
||||
|
||||
$this->syncOriginal();
|
||||
|
||||
@@ -1101,22 +1140,19 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
return;
|
||||
}
|
||||
|
||||
$this->fireModelEvent(new Events\Updating($this));
|
||||
$this->dispatch('updating');
|
||||
|
||||
$this->newQuery()->update($this->dn, $modifications);
|
||||
|
||||
$this->fireModelEvent(new Events\Updated($this));
|
||||
$this->dispatch('updated');
|
||||
|
||||
$this->syncOriginal();
|
||||
|
||||
$this->modifications = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the model in the directory.
|
||||
*
|
||||
* @param array $attributes The attributes for the new entry.
|
||||
*
|
||||
* @param array $attributes The attributes for the new entry.
|
||||
* @return Model
|
||||
*
|
||||
* @throws \LdapRecord\LdapRecordException
|
||||
@@ -1133,9 +1169,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Create an attribute on the model.
|
||||
*
|
||||
* @param string $attribute The attribute to create
|
||||
* @param mixed $value The value of the new attribute
|
||||
*
|
||||
* @param string $attribute The attribute to create
|
||||
* @param mixed $value The value of the new attribute
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
@@ -1143,18 +1178,21 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function createAttribute($attribute, $value)
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
$this->dispatch(['saving', 'updating']);
|
||||
|
||||
$this->newQuery()->insertAttributes($this->dn, [$attribute => (array) $value]);
|
||||
|
||||
$this->addAttributeValue($attribute, $value);
|
||||
|
||||
$this->dispatch(['updated', 'saved']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the model.
|
||||
*
|
||||
* @param array $attributes The attributes to update for the current entry.
|
||||
*
|
||||
* @param array $attributes The attributes to update for the current entry.
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
@@ -1162,7 +1200,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function update(array $attributes = [])
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
$this->save($attributes);
|
||||
}
|
||||
@@ -1170,9 +1208,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Update the model attribute with the specified value.
|
||||
*
|
||||
* @param string $attribute The attribute to modify
|
||||
* @param mixed $value The new value for the attribute
|
||||
*
|
||||
* @param string $attribute The attribute to modify
|
||||
* @param mixed $value The new value for the attribute
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
@@ -1180,19 +1217,22 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function updateAttribute($attribute, $value)
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
$this->dispatch(['saving', 'updating']);
|
||||
|
||||
$this->newQuery()->updateAttributes($this->dn, [$attribute => (array) $value]);
|
||||
|
||||
$this->addAttributeValue($attribute, $value);
|
||||
|
||||
$this->dispatch(['updated', 'saved']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the models for the given distinguished names.
|
||||
*
|
||||
* @param Collection|array|string $dns
|
||||
* @param bool $recursive
|
||||
*
|
||||
* @param Collection|array|string $dns
|
||||
* @param bool $recursive
|
||||
* @return int
|
||||
*
|
||||
* @throws \LdapRecord\LdapRecordException
|
||||
@@ -1201,11 +1241,17 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
$dns = is_string($dns) ? (array) $dns : $dns;
|
||||
|
||||
$instance = new static();
|
||||
|
||||
foreach ($dns as $dn) {
|
||||
if ($dns instanceof Collection) {
|
||||
$dns = $dns->modelDns()->toArray();
|
||||
}
|
||||
|
||||
// Here we are iterating through each distinguished name and locating
|
||||
// the associated model. While it's more resource intensive, we must
|
||||
// do this in case of leaf nodes being given alongside any parent
|
||||
// node, ensuring they can be deleted inside of the directory.
|
||||
foreach ((array) $dns as $dn) {
|
||||
if (! $model = $instance->find($dn)) {
|
||||
continue;
|
||||
}
|
||||
@@ -1224,8 +1270,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
* Throws a ModelNotFoundException if the current model does
|
||||
* not exist or does not contain a distinguished name.
|
||||
*
|
||||
* @param bool $recursive Whether to recursively delete leaf nodes (models that are children).
|
||||
*
|
||||
* @param bool $recursive Whether to recursively delete leaf nodes (models that are children).
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
@@ -1233,9 +1278,9 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function delete($recursive = false)
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
$this->fireModelEvent(new Events\Deleting($this));
|
||||
$this->dispatch('deleting');
|
||||
|
||||
if ($recursive) {
|
||||
$this->deleteLeafNodes();
|
||||
@@ -1248,7 +1293,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
// developers can hook in and run further operations.
|
||||
$this->exists = false;
|
||||
|
||||
$this->fireModelEvent(new Events\Deleted($this));
|
||||
$this->dispatch('deleted');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1263,15 +1308,15 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
$this->newQueryWithoutScopes()
|
||||
->in($this->dn)
|
||||
->listing()
|
||||
->chunk(250, function ($models) {
|
||||
$models->each->delete($recursive = true);
|
||||
->each(function (Model $model) {
|
||||
$model->delete($recursive = true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an attribute on the model.
|
||||
*
|
||||
* @param string|array $attributes The attribute(s) to delete
|
||||
* @param string|array $attributes The attribute(s) to delete
|
||||
*
|
||||
* Delete specific values in attributes:
|
||||
*
|
||||
@@ -1280,7 +1325,6 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
* Delete an entire attribute:
|
||||
*
|
||||
* ["memberuid" => []]
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
@@ -1288,10 +1332,12 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function deleteAttribute($attributes)
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
$attributes = $this->makeDeletableAttributes($attributes);
|
||||
|
||||
$this->dispatch(['saving', 'updating']);
|
||||
|
||||
$this->newQuery()->deleteAttributes($this->dn, $attributes);
|
||||
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
@@ -1311,14 +1357,15 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
}
|
||||
}
|
||||
|
||||
$this->dispatch(['updated', 'saved']);
|
||||
|
||||
$this->syncOriginal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a deletable attribute array.
|
||||
*
|
||||
* @param string|array $attributes
|
||||
*
|
||||
* @param string|array $attributes
|
||||
* @return array
|
||||
*/
|
||||
protected function makeDeletableAttributes($attributes)
|
||||
@@ -1339,9 +1386,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*
|
||||
* For example: $user->move($ou);
|
||||
*
|
||||
* @param static|string $newParentDn The new parent of the current model.
|
||||
* @param bool $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
|
||||
*
|
||||
* @param static|string $newParentDn The new parent of the current model.
|
||||
* @param bool $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
|
||||
* @return void
|
||||
*
|
||||
* @throws UnexpectedValueException
|
||||
@@ -1350,7 +1396,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function move($newParentDn, $deleteOldRdn = true)
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
if (! $rdn = $this->getRdn()) {
|
||||
throw new UnexpectedValueException('Current model does not contain an RDN to move.');
|
||||
@@ -1362,10 +1408,9 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Rename the model to a new RDN and new parent.
|
||||
*
|
||||
* @param string $rdn The models new relative distinguished name. Example: "cn=JohnDoe"
|
||||
* @param static|string|null $newParentDn The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
|
||||
* @param bool|true $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
|
||||
*
|
||||
* @param string $rdn The models new relative distinguished name. Example: "cn=JohnDoe"
|
||||
* @param static|string|null $newParentDn The models new parent distinguished name (if moving). Leave this null if you are only renaming. Example: "ou=MovedUsers,dc=acme,dc=org"
|
||||
* @param bool|true $deleteOldRdn Whether to delete the old models relative distinguished name once renamed / moved.
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
@@ -1373,7 +1418,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
*/
|
||||
public function rename($rdn, $newParentDn = null, $deleteOldRdn = true)
|
||||
{
|
||||
$this->requireExistence();
|
||||
$this->assertExists();
|
||||
|
||||
if ($newParentDn instanceof self) {
|
||||
$newParentDn = $newParentDn->getDn();
|
||||
@@ -1400,7 +1445,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
$rdn = $this->getUpdateableRdn($rdn);
|
||||
}
|
||||
|
||||
$this->fireModelEvent(new Renaming($this, $rdn, $newParentDn));
|
||||
$this->dispatch('renaming', [$rdn, $newParentDn]);
|
||||
|
||||
$this->newQuery()->rename($this->dn, $rdn, $newParentDn, $deleteOldRdn);
|
||||
|
||||
@@ -1420,7 +1465,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
= $this->original[$modelNameAttribute]
|
||||
= [reset($map[$modelNameAttribute])];
|
||||
|
||||
$this->fireModelEvent(new Renamed($this));
|
||||
$this->dispatch('renamed');
|
||||
|
||||
$this->wasRecentlyRenamed = true;
|
||||
}
|
||||
@@ -1428,8 +1473,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get an updateable RDN for the model.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getUpdateableRdn($name)
|
||||
@@ -1440,9 +1484,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get a distinguished name that is creatable for the model.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param string|null $attribute
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param string|null $attribute
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatableDn($name = null, $attribute = null)
|
||||
@@ -1456,9 +1499,8 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Get a creatable (escaped) RDN for the model.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param string|null $attribute
|
||||
*
|
||||
* @param string|null $name
|
||||
* @param string|null $attribute
|
||||
* @return string
|
||||
*/
|
||||
public function getCreatableRdn($name = null, $attribute = null)
|
||||
@@ -1485,8 +1527,7 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Determines if the given modification is valid.
|
||||
*
|
||||
* @param mixed $mod
|
||||
*
|
||||
* @param mixed $mod
|
||||
* @return bool
|
||||
*/
|
||||
protected function isValidModification($mod)
|
||||
@@ -1528,11 +1569,25 @@ abstract class Model implements ArrayAccess, Arrayable, JsonSerializable
|
||||
/**
|
||||
* Throw an exception if the model does not exist.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
*/
|
||||
protected function requireExistence()
|
||||
{
|
||||
return $this->assertExists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception if the model does not exist.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ModelDoesNotExistException
|
||||
*/
|
||||
protected function assertExists()
|
||||
{
|
||||
if (! $this->exists || is_null($this->dn)) {
|
||||
throw ModelDoesNotExistException::forModel($this);
|
||||
|
||||
@@ -16,8 +16,7 @@ class ModelDoesNotExistException extends LdapRecordException
|
||||
/**
|
||||
* Create a new exception for the given model.
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Model $model
|
||||
* @return ModelDoesNotExistException
|
||||
*/
|
||||
public static function forModel(Model $model)
|
||||
@@ -28,8 +27,7 @@ class ModelDoesNotExistException extends LdapRecordException
|
||||
/**
|
||||
* Set the model that does not exist.
|
||||
*
|
||||
* @param Model $model
|
||||
*
|
||||
* @param Model $model
|
||||
* @return ModelDoesNotExistException
|
||||
*/
|
||||
public function setModel(Model $model)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user