mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-02-09 05:51:38 +00:00
Merge branch 'staging' into feat/valkey
This commit is contained in:
@@ -1,21 +1,31 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.admin.inc.php';
|
||||
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /');
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /domainadmin/mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
elseif (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true;
|
||||
$olefy_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_OLEFY"])) ? false : true;
|
||||
|
||||
|
||||
if (!isset($_SESSION['gal']) && $license_cache = $valkey->Get('LICENSE_STATUS_CACHE')) {
|
||||
$_SESSION['gal'] = json_decode($license_cache, true);
|
||||
}
|
||||
|
||||
$js_minifier->add('/web/js/site/debug.js');
|
||||
$js_minifier->add('/web/js/site/dashboard.js');
|
||||
|
||||
// vmail df
|
||||
$exec_fields = array('cmd' => 'system', 'task' => 'df', 'dir' => '/var/vmail');
|
||||
@@ -24,6 +34,7 @@ $vmail_df = explode(',', (string)json_decode(docker('post', 'dovecot-mailcow', '
|
||||
// containers
|
||||
$containers_info = (array) docker('info');
|
||||
if ($clamd_status === false) unset($containers_info['clamd-mailcow']);
|
||||
if ($olefy_status === false) unset($containers_info['olefy-mailcow']);
|
||||
ksort($containers_info);
|
||||
$containers = array();
|
||||
foreach ($containers_info as $container => $container_info) {
|
||||
@@ -59,7 +70,7 @@ foreach ($containers_info as $container => $container_info) {
|
||||
$hostname = getenv('MAILCOW_HOSTNAME');
|
||||
$timezone = getenv('TZ');
|
||||
|
||||
$template = 'debug.twig';
|
||||
$template = 'dashboard.twig';
|
||||
$template_data = [
|
||||
'log_lines' => getenv('LOG_LINES'),
|
||||
'vmail_df' => $vmail_df,
|
||||
@@ -68,6 +79,7 @@ $template_data = [
|
||||
'gal' => @$_SESSION['gal'],
|
||||
'license_guid' => license('guid'),
|
||||
'clamd_status' => $clamd_status,
|
||||
'olefy_status' => $olefy_status,
|
||||
'containers' => $containers,
|
||||
'ip_check' => customize('get', 'ip_check'),
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
30
data/web/admin/index.php
Normal file
30
data/web/admin/index.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.admin.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /admin/dashboard');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /domainadmin/mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$_SESSION['index_query_string'] = $_SERVER['QUERY_STRING'];
|
||||
|
||||
|
||||
$template = 'admin_index.twig';
|
||||
$template_data = [
|
||||
'login_delay' => @$_SESSION['ldelay'],
|
||||
'custom_login' => customize('get', 'custom_login'),
|
||||
];
|
||||
|
||||
$js_minifier->add('/web/js/site/index.js');
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
@@ -1,10 +1,20 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.admin.inc.php';
|
||||
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
|
||||
header('Location: /');
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /domainadmin/mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
elseif (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
|
||||
@@ -14,7 +24,7 @@ $js_minifier->add('/web/js/site/mailbox.js');
|
||||
$js_minifier->add('/web/js/presets/sieveMailbox.js');
|
||||
$js_minifier->add('/web/js/site/pwgen.js');
|
||||
|
||||
$role = ($_SESSION['mailcow_cc_role'] == "admin") ? 'admin' : 'domainadmin';
|
||||
$role = "admin";
|
||||
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? 'true' : 'false';
|
||||
$allow_admin_email_login = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN"])) ? 'true' : 'false';
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.admin.inc.php';
|
||||
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /');
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /domainadmin/mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
elseif (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
}
|
||||
|
||||
@@ -11,7 +20,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$js_minifier->add('/web/js/site/queue.js');
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
|
||||
$role = ($_SESSION['mailcow_cc_role'] == "admin") ? 'admin' : 'domainadmin';
|
||||
$role = "admin";
|
||||
|
||||
$template = 'queue.twig';
|
||||
$template_data = [
|
||||
@@ -1,8 +1,17 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.admin.inc.php';
|
||||
|
||||
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /');
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /domainadmin/mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
elseif (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "admin") {
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
}
|
||||
|
||||
@@ -86,6 +95,8 @@ $cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allo
|
||||
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
||||
|
||||
$f2b_data = fail2ban('get');
|
||||
// mbox templates
|
||||
$mbox_templates = mailbox('get', 'mailbox_templates');
|
||||
|
||||
$template = 'admin.twig';
|
||||
$template_data = [
|
||||
@@ -114,10 +125,13 @@ $template_data = [
|
||||
'logo_specs' => customize('get', 'main_logo_specs'),
|
||||
'logo_dark_specs' => customize('get', 'main_logo_dark_specs'),
|
||||
'ip_check' => customize('get', 'ip_check'),
|
||||
'custom_login' => customize('get', 'custom_login'),
|
||||
'password_complexity' => password_complexity('get'),
|
||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||
'cors_settings' => $cors_settings,
|
||||
'is_https' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
||||
'iam_settings' => $iam_settings,
|
||||
'mbox_templates' => $mbox_templates,
|
||||
'lang_admin' => json_encode($lang['admin']),
|
||||
'lang_datatables' => json_encode($lang['datatables'])
|
||||
];
|
||||
@@ -346,7 +346,8 @@ paths:
|
||||
description: the domain which emails should be forwarded
|
||||
type: string
|
||||
type:
|
||||
description: the type of bcc map can be `sender` or `recipient`
|
||||
description: the type of bcc map can be `sender` or `rcpt`
|
||||
enum: [sender, rcpt]
|
||||
type: string
|
||||
type: object
|
||||
summary: Create BCC Map
|
||||
@@ -409,7 +410,7 @@ paths:
|
||||
description: a list of domains for which a dkim key should be generated
|
||||
type: string
|
||||
key_size:
|
||||
description: the key size (1024 or 2048)
|
||||
description: the key size (1024, 2048, 3072 or 4096)
|
||||
type: number
|
||||
type: object
|
||||
summary: Generate DKIM Key
|
||||
@@ -1112,6 +1113,7 @@ paths:
|
||||
domain: domain.tld
|
||||
local_part: info
|
||||
name: Full name
|
||||
authsource: mailcow
|
||||
password: atedismonsin
|
||||
password2: atedismonsin
|
||||
quota: "3072"
|
||||
@@ -1132,11 +1134,16 @@ paths:
|
||||
name:
|
||||
description: Full name of the mailbox user
|
||||
type: string
|
||||
authsource:
|
||||
description: Specifies the authentication source for the mailbox.
|
||||
type: string
|
||||
enum: [mailcow, ldap, keycloak, generic-oidc]
|
||||
default: mailcow
|
||||
password2:
|
||||
description: mailbox password for confirmation
|
||||
type: string
|
||||
password:
|
||||
description: mailbox password
|
||||
description: mailbox password when using `mailcow` as the authentication source.
|
||||
type: string
|
||||
quota:
|
||||
description: mailbox quota
|
||||
@@ -3374,6 +3381,7 @@ paths:
|
||||
active: "1"
|
||||
force_pw_update: "0"
|
||||
name: Full name
|
||||
authsource: mailcow
|
||||
password: ""
|
||||
password2: ""
|
||||
quota: "3072"
|
||||
@@ -3398,11 +3406,15 @@ paths:
|
||||
name:
|
||||
description: Full name of the mailbox user
|
||||
type: string
|
||||
authsource:
|
||||
description: Specifies the authentication source for the mailbox.
|
||||
type: string
|
||||
enum: [mailcow, ldap, keycloak, generic-oidc]
|
||||
password2:
|
||||
description: new mailbox password for confirmation
|
||||
type: string
|
||||
password:
|
||||
description: new mailbox password
|
||||
description: new mailbox password when using `mailcow` as the authentication source.
|
||||
type: string
|
||||
quota:
|
||||
description: mailbox quota
|
||||
@@ -5687,7 +5699,7 @@ paths:
|
||||
- description: name of domain
|
||||
in: path
|
||||
name: domain
|
||||
required: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: e.g. api-key-string
|
||||
@@ -5814,6 +5826,226 @@ paths:
|
||||
Using this endpoint you can get the global spam filter score or the spam filter score of a certain mailbox.
|
||||
operationId: Get mailbox or global spam filter score
|
||||
summary: Get mailbox or global spam filter score
|
||||
/api/v1/edit/identity-provider:
|
||||
post:
|
||||
responses:
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
response:
|
||||
value:
|
||||
- type: "success"
|
||||
log:
|
||||
- "identity_provider"
|
||||
- "edit"
|
||||
- authsource: "keycloak"
|
||||
server_url: "https://auth.mailcow.tld"
|
||||
realm: "mailcow"
|
||||
client_id: "mailcow_client"
|
||||
client_secret: "*"
|
||||
redirect_url: "https://mail.mailcow.tld"
|
||||
redirect_url_extra: ["https://extramail.mailcow.tld"]
|
||||
version: "26.1.3"
|
||||
default_template: "Default"
|
||||
mappers:
|
||||
- "small_mbox"
|
||||
- "medium_mbox"
|
||||
templates:
|
||||
- "small"
|
||||
- "medium"
|
||||
ignore_ssl_error: true
|
||||
mailpassword_flow: true
|
||||
periodic_sync: true
|
||||
import_users: true
|
||||
sync_interval: 30
|
||||
msg:
|
||||
- "object_modified"
|
||||
- ""
|
||||
description: OK
|
||||
headers: { }
|
||||
tags:
|
||||
- Identity Provider
|
||||
description: >-
|
||||
Configure an external Identity Provider to use as user authentication
|
||||
operationId: Edit external Identity Provider settings
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
items:
|
||||
type: array
|
||||
default: ["identity-provider"]
|
||||
attr:
|
||||
type: object
|
||||
properties:
|
||||
authsource:
|
||||
description: Specifies the type of the Identity Provider
|
||||
type: string
|
||||
enum: [ldap, keycloak, generic-oidc]
|
||||
server_url:
|
||||
description: The base URL of your Keycloak server. Required if `authsource` is keycloak.
|
||||
type: string
|
||||
realm:
|
||||
description: The Keycloak realm where the mailcow client is configured. Required if `authsource` is keycloak.
|
||||
type: string
|
||||
client_id:
|
||||
description: The Client ID assigned to mailcow Client in OIDC Provider. Required if `authsource` is keycloak or generic-oidc.
|
||||
type: string
|
||||
client_secret:
|
||||
description: The Client Secret assigned to mailcow Client in OIDC Provider. Required if `authsource` is keycloak or generic-oidc.
|
||||
type: string
|
||||
redirect_url:
|
||||
description: The redirect URL that OIDC Provider will use after authentication. Required if `authsource` is keycloak or generic-oidc.
|
||||
type: string
|
||||
redirect_url_extra:
|
||||
description: Additional redirect URLs that OIDC Provider can use after authentication if valid.
|
||||
type: array
|
||||
version:
|
||||
description: Specifies the Keycloak version. Required if `authsource` is keycloak.
|
||||
type: string
|
||||
default_template:
|
||||
description: (Optional) If no matching Attribute Mapping exists for a User, the default template will be used for creating the mailbox, but not for updating the mailbox.
|
||||
type: string
|
||||
mappers:
|
||||
description: (Optional) Attribute values used to match a mailbox template. Each element corresponds to the respective index in the templates array (i.e., the first element matches the first element of templates, the second matches the second, and so on).
|
||||
type: array
|
||||
templates:
|
||||
description: (Optional) Defines the mailbox templates to be assigned. Each element corresponds to the respective index in the `mappers` array.
|
||||
type: array
|
||||
ignore_ssl_error:
|
||||
description: If enabled, SSL certificate validation is bypassed
|
||||
type: boolean
|
||||
default: false
|
||||
mailpassword_flow:
|
||||
description: If enabled, mailcow will attempt to validate user credentials using the Keycloak Admin REST API instead of relying solely on the Authorization Code Flow.
|
||||
type: boolean
|
||||
default: false
|
||||
periodic_sync:
|
||||
description: If enabled, mailcow periodically performs a full sync of all users from Keycloak or LDAP.
|
||||
type: boolean
|
||||
default: false
|
||||
import_users:
|
||||
description: If enabled, new users are automatically imported from Keycloak or LDAP into mailcow.
|
||||
type: boolean
|
||||
default: false
|
||||
sync_interval:
|
||||
description: Defines the time interval (in minutes) for periodic synchronization and user imports.
|
||||
type: number
|
||||
default: 15
|
||||
host:
|
||||
description: The address of your LDAP server. You can provide a single hostname or a comma-separated list of hosts for fallback in case the primary server is unreachable. Required if `authsource` is ldap.
|
||||
type: string
|
||||
port:
|
||||
description: The port used to connect to the LDAP server. Required if `authsource` is ldap.
|
||||
type: string
|
||||
use_ssl:
|
||||
description: enable LDAPS connection. If Port is set to 389 it will be overriden to 636.
|
||||
type: boolean
|
||||
default: false
|
||||
use_tls:
|
||||
description: enable TLS connection. TLS is recommended over SSL. SSL Ports cannot be used.
|
||||
type: boolean
|
||||
default: false
|
||||
basedn:
|
||||
description: The Distinguished Name (DN) from which searches will be performed. Required if `authsource` is ldap.
|
||||
type: string
|
||||
username_field:
|
||||
description: The LDAP attribute used to identify users during authentication. Required if `authsource` is ldap.
|
||||
type: string
|
||||
default: mail
|
||||
filter:
|
||||
description: An optional LDAP search filter to refine which users can authenticate.
|
||||
type: string
|
||||
attribute_field:
|
||||
description: Specifies an LDAP attribute that holds a specific value which can be mapped to a mailbox template using the Attribute Mapping section. Required if `authsource` is ldap.
|
||||
type: string
|
||||
binddn:
|
||||
description: The Distinguished Name (DN) of the LDAP user that will be used to authenticate and perform LDAP searches. This account should have sufficient permissions to read the required attributes. Required if `authsource` is ldap.
|
||||
type: string
|
||||
bindpass:
|
||||
description: The password for the Bind DN user. It is required for authentication when connecting to the LDAP server. Required if `authsource` is ldap.
|
||||
type: string
|
||||
authorize_url:
|
||||
description: The OIDC provider's authorization server URL. Required if `authsource` is generic-oidc.
|
||||
type: string
|
||||
token_url:
|
||||
description: The OIDC provider's token server URL. Required if `authsource` is generic-oidc.
|
||||
type: string
|
||||
userinfo_url:
|
||||
description: The OIDC provider's user info server URL. Required if `authsource` is generic-oidc.
|
||||
type: string
|
||||
client_scopes:
|
||||
description: Specifies the OIDC scopes requested during authentication.
|
||||
type: string
|
||||
default: "openid profile email mailcow_template"
|
||||
examples:
|
||||
keycloak:
|
||||
value:
|
||||
items:
|
||||
- "identity-provider"
|
||||
attr:
|
||||
authsource: "keycloak"
|
||||
server_url: "https://auth.mailcow.tld"
|
||||
realm: "mailcow"
|
||||
client_id: "mailcow_client"
|
||||
client_secret: "Xy7GdPqvJ9m3R8sT2LkVZ5W1oNbCaYQf"
|
||||
redirect_url: "https://mail.mailcow.tld"
|
||||
redirect_url_extra: ["https://extramail.mailcow.tld"]
|
||||
version: "26.1.3"
|
||||
default_template: "Default"
|
||||
mappers: ["small_mbox", "medium_mbox"]
|
||||
templates: ["small", "medium"]
|
||||
ignore_ssl_error: true
|
||||
mailpassword_flow: true
|
||||
periodic_sync: true
|
||||
import_users: true
|
||||
sync_interval: 30
|
||||
ldap:
|
||||
value:
|
||||
items:
|
||||
- "identity-provider"
|
||||
attr:
|
||||
authsource: "ldap"
|
||||
host: "127.0.0.1"
|
||||
port: "389"
|
||||
use_ssl: false
|
||||
use_tls: false
|
||||
ignore_ssl_error: false
|
||||
basedn: "DC=mailcow,DC=local"
|
||||
username_field: "mail"
|
||||
filter: "(memberOf:1.2.840.113556.1.4.1941:=DC=mailcow,DC=local)"
|
||||
attribute_field: "othermailbox"
|
||||
binddn: "CN=LDAP Read Only,CN=Users,DC=mailcow,DC=local"
|
||||
bindpass: "moohoo"
|
||||
default_template: "Default"
|
||||
mappers: ["small_mbox", "medium_mbox"]
|
||||
templates: ["small", "medium"]
|
||||
periodic_sync: true
|
||||
import_users: true
|
||||
sync_interval: 30
|
||||
generic-oidc:
|
||||
value:
|
||||
items:
|
||||
- "identity-provider"
|
||||
attr:
|
||||
authsource: "generic-oidc"
|
||||
authorize_url: "https://auth.mailcow.tld/application/o/authorize/"
|
||||
token_url: "https://auth.mailcow.tld/application/o/token/"
|
||||
userinfo_url: "https://auth.mailcow.tld/application/o/userinfo/"
|
||||
client_id: "mailcow_client"
|
||||
client_secret: "Xy7GdPqvJ9m3R8sT2LkVZ5W1oNbCaYQf"
|
||||
redirect_url: "https://mail.mailcow.tld"
|
||||
redirect_url_extra: ["https://extramail.mailcow.tld"]
|
||||
client_scopes: "openid profile email mailcow_template"
|
||||
default_template: "Default"
|
||||
mappers: ["small_mbox", "medium_mbox"]
|
||||
templates: ["small", "medium"]
|
||||
ignore_ssl_error: true
|
||||
summary: Edit external Identity Provider
|
||||
|
||||
tags:
|
||||
- name: Domains
|
||||
@@ -5860,3 +6092,5 @@ tags:
|
||||
description: Edit domain ratelimits
|
||||
- name: Cross-Origin Resource Sharing (CORS)
|
||||
description: Manage Cross-Origin Resource Sharing (CORS) settings
|
||||
- name: Identity Provider
|
||||
description: Manage external Identity Provider settings
|
||||
|
||||
@@ -85,7 +85,7 @@ if (count($records) == 0 || $records[0]['target'] != '') { ?>
|
||||
<authentication>password-cleartext</authentication>
|
||||
</outgoingServer>
|
||||
|
||||
<enable visiturl="https://<?=$mailcow_hostname; ?><?php if ($port != 443) echo ':'.$port; ?>/admin.php">
|
||||
<enable visiturl="https://<?=$mailcow_hostname; ?><?php if ($port != 443) echo ':'.$port; ?>/admin">
|
||||
<instruction>If you didn't change the password given to you by the administrator or if you didn't change it in a long time, please consider doing that now.</instruction>
|
||||
<instruction lang="de">Sollten Sie das Ihnen durch den Administrator vergebene Passwort noch nicht geändert haben, empfehlen wir dies nun zu tun. Auch ein altes Passwort sollte aus Sicherheitsgründen geändert werden.</instruction>
|
||||
</enable>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/vendor/autoload.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
|
||||
$default_autodiscover_config = $autodiscover_config;
|
||||
if(file_exists('inc/vars.local.inc.php')) {
|
||||
include_once 'inc/vars.local.inc.php';
|
||||
}
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.auth.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
|
||||
$default_autodiscover_config = $autodiscover_config;
|
||||
$autodiscover_config = array_merge($default_autodiscover_config, $autodiscover_config);
|
||||
|
||||
// Valkey
|
||||
@@ -50,6 +53,11 @@ $opt = [
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
];
|
||||
$pdo = new PDO($dsn, $database_user, $database_pass, $opt);
|
||||
|
||||
// Init Identity Provider
|
||||
$iam_provider = identity_provider('init');
|
||||
$iam_settings = identity_provider('get');
|
||||
|
||||
$login_user = strtolower(trim($_SERVER['PHP_AUTH_USER']));
|
||||
$login_pass = trim(htmlspecialchars_decode($_SERVER['PHP_AUTH_PW']));
|
||||
|
||||
|
||||
2
data/web/css/build/007-languages.min.css
vendored
2
data/web/css/build/007-languages.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -8,9 +8,6 @@
|
||||
.dtr-details {
|
||||
width: 100%;
|
||||
}
|
||||
.table-striped>tbody>tr:nth-of-type(odd) {
|
||||
background-color: #F2F2F2;
|
||||
}
|
||||
td.child>ul>li {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
url('/fonts/noto-sans-v12-latin_greek_cyrillic-700italic.woff2') format('woff2'),
|
||||
url('/fonts/noto-sans-v12-latin_greek_cyrillic-700italic.woff') format('woff');
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fbfbfb;
|
||||
}
|
||||
#maxmsgsize { min-width: 80px; }
|
||||
#slider1 .slider-selection {
|
||||
background: #FFD700;
|
||||
@@ -74,10 +81,23 @@
|
||||
align-items: center;
|
||||
padding: 0 10px !important;
|
||||
}
|
||||
.navbar-fixed-bottom .navbar-collapse,
|
||||
.navbar-fixed-bottom .navbar-collapse,
|
||||
.navbar-fixed-top .navbar-collapse {
|
||||
max-height: 1000px
|
||||
}
|
||||
.nav-tabs .nav-link, .nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:hover, .nav-tabs .nav-link.disabled:focus {
|
||||
border-color: #dfdfdf;
|
||||
}
|
||||
.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
|
||||
border-color: #dfdfdf;
|
||||
border-bottom: 1px solid #ffffff;
|
||||
}
|
||||
.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {
|
||||
border-color: #dfdfdf;
|
||||
}
|
||||
.nav-tabs {
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
}
|
||||
.bi {
|
||||
display: inline-block;
|
||||
font-size: 12pt;
|
||||
@@ -123,18 +143,18 @@
|
||||
}
|
||||
}
|
||||
@keyframes blink {
|
||||
50% {
|
||||
color: transparent
|
||||
50% {
|
||||
color: transparent
|
||||
}
|
||||
}
|
||||
.loader-dot {
|
||||
animation: 1s blink infinite
|
||||
.loader-dot {
|
||||
animation: 1s blink infinite
|
||||
}
|
||||
.loader-dot:nth-child(2) {
|
||||
animation-delay: 250ms
|
||||
.loader-dot:nth-child(2) {
|
||||
animation-delay: 250ms
|
||||
}
|
||||
.loader-dot:nth-child(3) {
|
||||
animation-delay: 500ms
|
||||
.loader-dot:nth-child(3) {
|
||||
animation-delay: 500ms
|
||||
}
|
||||
|
||||
pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;}
|
||||
@@ -200,13 +220,13 @@ legend {
|
||||
}
|
||||
.haveibeenpwned {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.full-width-select {
|
||||
width: 100%!important;
|
||||
width: 100%!important;
|
||||
}
|
||||
.tooltip {
|
||||
font-family: inherit;
|
||||
@@ -330,7 +350,7 @@ code {
|
||||
.caret {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
a[aria-expanded='true'] > .caret,
|
||||
a[aria-expanded='true'] > .caret,
|
||||
button[aria-expanded='true'] > .caret {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
@@ -340,7 +360,7 @@ button[aria-expanded='true'] > .caret {
|
||||
}
|
||||
.list-group-header {
|
||||
background: #f7f7f7;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.bg-primary, .alert-primary, .btn-primary {
|
||||
@@ -366,12 +386,13 @@ button[aria-expanded='true'] > .caret {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
.btn.btn-outline-secondary {
|
||||
border-color: #cfcfcf !important;
|
||||
color: #000000 !important;
|
||||
border-color: #cfcfcf !important;
|
||||
}
|
||||
.btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show {
|
||||
background-color: #f0f0f0 !important;
|
||||
}
|
||||
.btn-check:checked+.btn-light, .btn-check:active+.btn-light, .btn-light:active, .btn-light.active, .show>.btn-light.dropdown-toggle {
|
||||
.btn-check:checked+.btn-light, .btn-check:active+.btn-light, .btn-light:active, .btn-light.active, .show>.btn-light.dropdown-toggle {
|
||||
color: #fff;
|
||||
background-color: #555;
|
||||
background-image: none;
|
||||
@@ -389,4 +410,26 @@ button[aria-expanded='true'] > .caret {
|
||||
.badge.bg-danger > a {
|
||||
color: #fff !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.hr-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.hr-title::before,
|
||||
.hr-title::after {
|
||||
content: "";
|
||||
flex: 1;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.hr-title:not(:empty)::before {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.hr-title:not(:empty)::after {
|
||||
margin-left: 10px;
|
||||
}
|
||||
@@ -6,15 +6,9 @@
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.card-login .apps .btn {
|
||||
width: auto;
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
margin-top: auto;
|
||||
}
|
||||
.card-login .apps .btn:hover {
|
||||
margin-top: 1px !important;
|
||||
border-bottom-width: 3px;
|
||||
.card .apps {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.responsive-tabs .nav-tabs {
|
||||
@@ -43,16 +37,6 @@
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.card-login .apps .btn {
|
||||
width: 100%;
|
||||
float: none;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.card-login .apps .btn {
|
||||
border-bottom-width: 4px;
|
||||
}
|
||||
|
||||
.xs-show {
|
||||
display: block !important;
|
||||
}
|
||||
@@ -113,9 +97,6 @@
|
||||
.btn-group.nowrap .dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
.card-login .btn-group {
|
||||
display: block;
|
||||
}
|
||||
.mass-actions-user .btn-group {
|
||||
float: none;
|
||||
}
|
||||
@@ -191,9 +172,6 @@
|
||||
.btn-group .btn i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.card-login .btn-group .btn {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.dt-sm-head-hidden .dtr-title {
|
||||
display: none !important;
|
||||
@@ -206,7 +184,7 @@
|
||||
.senders-mw220 {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
|
||||
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before,
|
||||
table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before,
|
||||
table.dataTable td.dt-control:before {
|
||||
@@ -215,7 +193,7 @@
|
||||
line-height: 2rem;
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
|
||||
li .dtr-data {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -59,9 +59,6 @@ body.modal-open {
|
||||
.table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td {
|
||||
padding: 3px;
|
||||
}
|
||||
table tbody tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
table tbody tr td input[type="checkbox"] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
29
data/web/domainadmin/index.php
Normal file
29
data/web/domainadmin/index.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.domainadmin.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /domainadmin/mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /admin/dashboard');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$_SESSION['index_query_string'] = $_SERVER['QUERY_STRING'];
|
||||
|
||||
$template = 'domainadmin_index.twig';
|
||||
$template_data = [
|
||||
'login_delay' => @$_SESSION['ldelay'],
|
||||
'custom_login' => customize('get', 'custom_login'),
|
||||
];
|
||||
|
||||
$js_minifier->add('/web/js/site/index.js');
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
58
data/web/domainadmin/mailbox.php
Normal file
58
data/web/domainadmin/mailbox.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.domainadmin.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /admin/dashboard');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
elseif (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "domainadmin") {
|
||||
header('Location: /domainadmin');
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
|
||||
|
||||
|
||||
$js_minifier->add('/web/js/site/mailbox.js');
|
||||
$js_minifier->add('/web/js/presets/sieveMailbox.js');
|
||||
$js_minifier->add('/web/js/site/pwgen.js');
|
||||
|
||||
$role = "domainadmin";
|
||||
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? 'true' : 'false';
|
||||
$allow_admin_email_login = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["ALLOW_ADMIN_EMAIL_LOGIN"])) ? 'true' : 'false';
|
||||
|
||||
// domains
|
||||
$domains = mailbox('get', 'domains');
|
||||
|
||||
// mailboxes
|
||||
$mailboxes = [];
|
||||
foreach ($domains as $domain) {
|
||||
foreach (mailbox('get', 'mailboxes', $domain) as $mailbox) {
|
||||
$mailboxes[] = $mailbox;
|
||||
}
|
||||
}
|
||||
|
||||
$template = 'mailbox.twig';
|
||||
$template_data = [
|
||||
'acl' => $_SESSION['acl'],
|
||||
'acl_json' => json_encode($_SESSION['acl']),
|
||||
'role' => $role,
|
||||
'is_dual' => $is_dual,
|
||||
'allow_admin_email_login' => $allow_admin_email_login,
|
||||
'global_filters' => mailbox('get', 'global_filter_details'),
|
||||
'domains' => $domains,
|
||||
'mailboxes' => $mailboxes,
|
||||
'lang_mailbox' => json_encode($lang['mailbox']),
|
||||
'lang_rl' => json_encode($lang['ratelimit']),
|
||||
'lang_edit' => json_encode($lang['edit']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
44
data/web/domainadmin/user.php
Normal file
44
data/web/domainadmin/user.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.domainadmin.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
|
||||
/*
|
||||
/ DOMAIN ADMIN
|
||||
*/
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$tfa_data = get_tfa();
|
||||
$fido2_data = fido2(array("action" => "get_friendly_names"));
|
||||
$username = $_SESSION['mailcow_cc_username'];
|
||||
|
||||
$template = 'domainadmin.twig';
|
||||
$template_data = [
|
||||
'acl' => $_SESSION['acl'],
|
||||
'acl_json' => json_encode($_SESSION['acl']),
|
||||
'user_spam_score' => mailbox('get', 'spam_score', $username),
|
||||
'tfa_data' => $tfa_data,
|
||||
'fido2_data' => $fido2_data,
|
||||
'lang_user' => json_encode($lang['user']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /admin/dashboard');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
else {
|
||||
header('Location: /domainadmin');
|
||||
exit();
|
||||
}
|
||||
|
||||
$js_minifier->add('/web/js/site/user.js');
|
||||
$js_minifier->add('/web/js/site/pwgen.js');
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
@@ -48,6 +48,12 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
$rl = ratelimit('get', 'domain', $domain);
|
||||
$rlyhosts = relayhost('get');
|
||||
$domain_footer = mailbox('get', 'domain_wide_footer', $domain);
|
||||
$mta_sts = mailbox('get', 'mta_sts', $domain);
|
||||
if (count($mta_sts) == 0) {
|
||||
$mta_sts = false;
|
||||
} elseif (isset($mta_sts['mx'])) {
|
||||
$mta_sts['mx'] = implode(',', $mta_sts['mx']);
|
||||
}
|
||||
$template = 'edit/domain.twig';
|
||||
$template_data = [
|
||||
'acl' => $_SESSION['acl'],
|
||||
@@ -58,6 +64,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
'dkim' => dkim('details', $domain),
|
||||
'domain_details' => $result,
|
||||
'domain_footer' => $domain_footer,
|
||||
'mta_sts' => $mta_sts,
|
||||
'mailboxes' => mailbox('get', 'mailboxes', $_GET["domain"]),
|
||||
'aliases' => mailbox('get', 'aliases', $_GET["domain"], 'address'),
|
||||
'alias_domains' => mailbox('get', 'alias_domains', $_GET["domain"])
|
||||
@@ -125,13 +132,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
'mailbox' => $mailbox,
|
||||
'rl' => $rl,
|
||||
'pushover_data' => $pushover_data,
|
||||
'get_tagging_options' => mailbox('get', 'delimiter_action', $mailbox),
|
||||
'quarantine_notification' => $quarantine_notification,
|
||||
'quarantine_category' => $quarantine_category,
|
||||
'get_tls_policy' => $get_tls_policy,
|
||||
'rlyhosts' => $rlyhosts,
|
||||
'sender_acl_handles' => mailbox('get', 'sender_acl_handles', $mailbox),
|
||||
'user_acls' => acl('get', 'user', $mailbox),
|
||||
'mailbox_details' => $result
|
||||
'mailbox_details' => $result,
|
||||
'iam_settings' => $iam_settings,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
@@ -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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user