mirror of
https://github.com/LDAPAccountManager/lam.git
synced 2025-10-03 09:49:16 +02:00
Merge remote-tracking branch 'origin/develop' into 413-update-dependencies-webauthn
This commit is contained in:
commit
f5172b6b5a
22 changed files with 725 additions and 159 deletions
|
@ -1,4 +1,4 @@
|
||||||
This software is copyright (c) 2003 - 2024 by Roland Gruber
|
This software is copyright (c) 2003 - 2025 by Roland Gruber
|
||||||
|
|
||||||
If you purchased a copy of LDAP Account Manager Pro then the following
|
If you purchased a copy of LDAP Account Manager Pro then the following
|
||||||
files are licensed under the conditions which you accepted at purchase
|
files are licensed under the conditions which you accepted at purchase
|
||||||
|
@ -17,6 +17,8 @@ time.
|
||||||
* lib/modules/automount.inc
|
* lib/modules/automount.inc
|
||||||
* lib/modules/bindDLZ.inc
|
* lib/modules/bindDLZ.inc
|
||||||
* lib/modules/bindDLZXfr.inc
|
* lib/modules/bindDLZXfr.inc
|
||||||
|
* lib/modules/bindDyndbRecord.inc
|
||||||
|
* lib/modules/bindDyndbZone.inc
|
||||||
* lib/modules/customBaseType.inc
|
* lib/modules/customBaseType.inc
|
||||||
* lib/modules/customFields.inc
|
* lib/modules/customFields.inc
|
||||||
* lib/modules/customScripts.inc
|
* lib/modules/customScripts.inc
|
||||||
|
@ -56,6 +58,7 @@ time.
|
||||||
* lib/modules/rfc2307bisAutomount.inc
|
* lib/modules/rfc2307bisAutomount.inc
|
||||||
* lib/modules/rfc2307bisPosixGroup.inc
|
* lib/modules/rfc2307bisPosixGroup.inc
|
||||||
* lib/modules/selfRegistration.inc
|
* lib/modules/selfRegistration.inc
|
||||||
|
* lib/modules/simpleSecurityObject.inc
|
||||||
* lib/modules/sudoRole.inc
|
* lib/modules/sudoRole.inc
|
||||||
* lib/modules/uidObject.inc
|
* lib/modules/uidObject.inc
|
||||||
* lib/modules/webauthn.inc
|
* lib/modules/webauthn.inc
|
||||||
|
@ -64,6 +67,7 @@ time.
|
||||||
* lib/types/alias.inc
|
* lib/types/alias.inc
|
||||||
* lib/types/automountType.inc
|
* lib/types/automountType.inc
|
||||||
* lib/types/bind.inc
|
* lib/types/bind.inc
|
||||||
|
* lib/types/bindDyndbType.inc
|
||||||
* lib/types/customType.inc
|
* lib/types/customType.inc
|
||||||
* lib/types/gon.inc
|
* lib/types/gon.inc
|
||||||
* lib/types/kopanoAddressListType.inc
|
* lib/types/kopanoAddressListType.inc
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
June 2025 9.2
|
June 2025 9.2
|
||||||
|
- TAK support added
|
||||||
- Active Directory: allow to restore deleted entries in tree view (415)
|
- Active Directory: allow to restore deleted entries in tree view (415)
|
||||||
|
- Fixed bugs:
|
||||||
|
-> Unix: profile editor for users not working (418)
|
||||||
|
-> Custom fields: problems with deleting facsimileTelephoneNumber (419)
|
||||||
|
|
||||||
13.03.2025 9.1
|
13.03.2025 9.1
|
||||||
- Usability improvements (347, 348, 360, 403)
|
- Usability improvements (347, 348, 360, 403)
|
||||||
|
|
|
@ -17,6 +17,8 @@ time.
|
||||||
* lib/modules/automount.inc
|
* lib/modules/automount.inc
|
||||||
* lib/modules/bindDLZ.inc
|
* lib/modules/bindDLZ.inc
|
||||||
* lib/modules/bindDLZXfr.inc
|
* lib/modules/bindDLZXfr.inc
|
||||||
|
* lib/modules/bindDyndbRecord.inc
|
||||||
|
* lib/modules/bindDyndbZone.inc
|
||||||
* lib/modules/customBaseType.inc
|
* lib/modules/customBaseType.inc
|
||||||
* lib/modules/customFields.inc
|
* lib/modules/customFields.inc
|
||||||
* lib/modules/customScripts.inc
|
* lib/modules/customScripts.inc
|
||||||
|
@ -56,6 +58,7 @@ time.
|
||||||
* lib/modules/rfc2307bisAutomount.inc
|
* lib/modules/rfc2307bisAutomount.inc
|
||||||
* lib/modules/rfc2307bisPosixGroup.inc
|
* lib/modules/rfc2307bisPosixGroup.inc
|
||||||
* lib/modules/selfRegistration.inc
|
* lib/modules/selfRegistration.inc
|
||||||
|
* lib/modules/simpleSecurityObject.inc
|
||||||
* lib/modules/sudoRole.inc
|
* lib/modules/sudoRole.inc
|
||||||
* lib/modules/uidObject.inc
|
* lib/modules/uidObject.inc
|
||||||
* lib/modules/webauthn.inc
|
* lib/modules/webauthn.inc
|
||||||
|
@ -64,6 +67,7 @@ time.
|
||||||
* lib/types/alias.inc
|
* lib/types/alias.inc
|
||||||
* lib/types/automountType.inc
|
* lib/types/automountType.inc
|
||||||
* lib/types/bind.inc
|
* lib/types/bind.inc
|
||||||
|
* lib/types/bindDyndbType.inc
|
||||||
* lib/types/customType.inc
|
* lib/types/customType.inc
|
||||||
* lib/types/gon.inc
|
* lib/types/gon.inc
|
||||||
* lib/types/kopanoAddressListType.inc
|
* lib/types/kopanoAddressListType.inc
|
||||||
|
@ -433,7 +437,7 @@ E:
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
F:
|
F:
|
||||||
3-Clause BSD License
|
3-Clause BSD License
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
|
@ -467,7 +467,7 @@
|
||||||
|
|
||||||
<entry>dhcp.schema</entry>
|
<entry>dhcp.schema</entry>
|
||||||
|
|
||||||
<entry>docs/schema/dhcp.schema</entry>
|
<entry>Part of LAM installation: docs/schema/dhcp.schema</entry>
|
||||||
|
|
||||||
<entry>The LDAP suffix should be set to your dhcpServer
|
<entry>The LDAP suffix should be set to your dhcpServer
|
||||||
entry.</entry>
|
entry.</entry>
|
||||||
|
@ -486,7 +486,7 @@
|
||||||
|
|
||||||
<entry>schema.ldif</entry>
|
<entry>schema.ldif</entry>
|
||||||
|
|
||||||
<entry>part of bind-dyndb-ldap</entry>
|
<entry>Part of bind-dyndb-ldap</entry>
|
||||||
|
|
||||||
<entry>LAM Pro only</entry>
|
<entry>LAM Pro only</entry>
|
||||||
</row>
|
</row>
|
||||||
|
@ -505,7 +505,7 @@
|
||||||
|
|
||||||
<entry>dlz.schema</entry>
|
<entry>dlz.schema</entry>
|
||||||
|
|
||||||
<entry>part of <ulink url="http://bind-dlz.sourceforge.net/">Bind
|
<entry>Part of <ulink url="http://bind-dlz.sourceforge.net/">Bind
|
||||||
DLZ patch</ulink></entry>
|
DLZ patch</ulink></entry>
|
||||||
|
|
||||||
<entry>LAM Pro only</entry>
|
<entry>LAM Pro only</entry>
|
||||||
|
@ -821,6 +821,24 @@
|
||||||
<entry>LAM Pro only, requires DDS extension on LDAP server
|
<entry>LAM Pro only, requires DDS extension on LDAP server
|
||||||
side</entry>
|
side</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><inlinemediaobject>
|
||||||
|
<imageobject>
|
||||||
|
<imagedata fileref="images/schema_tak.png" width="16px"/>
|
||||||
|
</imageobject>
|
||||||
|
</inlinemediaobject></entry>
|
||||||
|
|
||||||
|
<entry>TAK</entry>
|
||||||
|
|
||||||
|
<entry>takUser</entry>
|
||||||
|
|
||||||
|
<entry>tak-*.ldif</entry>
|
||||||
|
|
||||||
|
<entry>Part of LAM installation: docs/schema/tak-*.ldif</entry>
|
||||||
|
|
||||||
|
<entry/>
|
||||||
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -2510,6 +2510,56 @@ AuthorizedKeysCommandUser root</literallayout>
|
||||||
<graphic fileref="images/mod_lastBind3.png"/>
|
<graphic fileref="images/mod_lastBind3.png"/>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>TAK</title>
|
||||||
|
|
||||||
|
<para>The <ulink url="https://www.civtak.org/">TAK</ulink> module
|
||||||
|
supports the Team Awareness Kit or Tactical Assault Kit (TAK) with the
|
||||||
|
Android Team Awareness Kit (ATAK).</para>
|
||||||
|
|
||||||
|
<para>You can define callsigns, team roles and colors for users.</para>
|
||||||
|
|
||||||
|
<para><emphasis role="bold">LDAP schema</emphasis></para>
|
||||||
|
|
||||||
|
<para>The module expects that TAK users use the object class "takUser"
|
||||||
|
and the attributes "takCallsign", "takRole" and "takColor". You can find
|
||||||
|
matching schema files in /usr/share/ldap-account-manager/docs/schema
|
||||||
|
(DEB/RPM) or docs/schema (tar.bz2). Please see the beginning of the
|
||||||
|
files for installation instructions.</para>
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>OpenLDAP: tak-OpenLDAP.ldif</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Samba 4: tak-Samba4-attributes.ldif and
|
||||||
|
tak-Samba4-objectClass.ldif</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Windows (AD): tak-Windows.ldif</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
|
|
||||||
|
<para><emphasis role="bold">Configuration</emphasis></para>
|
||||||
|
|
||||||
|
<para>Add the TAK module for users in your server profile:</para>
|
||||||
|
|
||||||
|
<screenshot>
|
||||||
|
<graphic fileref="images/mod_tak1.png"/>
|
||||||
|
</screenshot>
|
||||||
|
|
||||||
|
<para>Now you can manage the TAK attributes for users.</para>
|
||||||
|
|
||||||
|
<para>LAM Pro users can add these attributes to the self-service profile
|
||||||
|
if needed.</para>
|
||||||
|
|
||||||
|
<screenshot>
|
||||||
|
<graphic fileref="images/mod_tak2.png"/>
|
||||||
|
</screenshot>
|
||||||
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
BIN
lam/docs/manual-sources/images/mod_tak1.png
Normal file
BIN
lam/docs/manual-sources/images/mod_tak1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
BIN
lam/docs/manual-sources/images/mod_tak2.png
Normal file
BIN
lam/docs/manual-sources/images/mod_tak2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
lam/docs/manual-sources/images/schema_tak.png
Normal file
BIN
lam/docs/manual-sources/images/schema_tak.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
33
lam/docs/schema/tak-OpenLDAP.ldif
Normal file
33
lam/docs/schema/tak-OpenLDAP.ldif
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#
|
||||||
|
# LDAP schema for LAM TAK functionality
|
||||||
|
#
|
||||||
|
# This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
# Copyright (C) 2025 Roland Gruber
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# OID bases:
|
||||||
|
# 1.3.6.1.4.1.34955 Roland Gruber Softwareentwicklung
|
||||||
|
# 1.3.6.1.4.1.34955.1 attributes
|
||||||
|
# 1.3.6.1.4.1.34955.2 object classes
|
||||||
|
#
|
||||||
|
# Installation:
|
||||||
|
# ldapadd -x -W -H ldap://localhost -D "cn=admin,dc=company,dc=com" -f tak-OpenLDAP.ldif
|
||||||
|
#
|
||||||
|
# Please replace "localhost" with your LDAP server and "cn=admin,dc=company,dc=com" with your LDAP admin user (usually starts with cn=admin or cn=manager).
|
||||||
|
#
|
||||||
|
# In some cases you might need to import directly on the OpenLDAP server as root:
|
||||||
|
# ldapadd -Y EXTERNAL -H ldapi:/// -f tak-OpenLDAP.ldif
|
||||||
|
#
|
||||||
|
# Version: 1
|
||||||
|
#
|
||||||
|
# Changelog:
|
||||||
|
# 1: initial release (LAM 9.2)
|
||||||
|
#
|
||||||
|
|
||||||
|
dn: cn=tak,cn=schema,cn=config
|
||||||
|
objectClass: olcSchemaConfig
|
||||||
|
cn: tak
|
||||||
|
olcAttributeTypes: ( 1.3.6.1.4.1.34955.1.100 NAME 'takCallsign' DESC 'TAK callsign' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
|
||||||
|
olcAttributeTypes: ( 1.3.6.1.4.1.34955.1.101 NAME 'takRole' DESC 'TAK team role' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
|
||||||
|
olcAttributeTypes: ( 1.3.6.1.4.1.34955.1.102 NAME 'takColor' DESC 'TAK team color' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
|
||||||
|
olcObjectClasses: ( 1.3.6.1.4.1.34955.2.10 NAME 'takUser' DESC 'TAK user' SUP top AUXILIARY MAY ( takCallsign $ takRole $ takColor ) MUST ( cn ) )
|
58
lam/docs/schema/tak-Samba4-attributes.ldif
Normal file
58
lam/docs/schema/tak-Samba4-attributes.ldif
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#
|
||||||
|
# LDAP schema for LAM TAK functionality
|
||||||
|
#
|
||||||
|
# This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
# Copyright (C) 2025 Roland Gruber
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# OID bases:
|
||||||
|
# 1.3.6.1.4.1.34955 Roland Gruber Softwareentwicklung
|
||||||
|
# 1.3.6.1.4.1.34955.1 attributes
|
||||||
|
# 1.3.6.1.4.1.34955.2 object classes
|
||||||
|
#
|
||||||
|
# Please replace DOMAIN_TOP_DN with your LDAP suffix (e.g. dc=samba4,dc=test).
|
||||||
|
# This file must be installed first.
|
||||||
|
#
|
||||||
|
# Installation: ldbmodify -H /var/lib/samba/private/sam.ldb tak-Samba4-attributes.ldif --option="dsdb:schema update allowed"=true
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Version: 1
|
||||||
|
# 1: initial release (LAM 9.2)
|
||||||
|
#
|
||||||
|
|
||||||
|
dn: CN=takCallsign,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
objectClass: top
|
||||||
|
objectClass: attributeSchema
|
||||||
|
attributeID: 1.3.6.1.4.1.34955.1.100
|
||||||
|
attributeSyntax: 2.5.5.12
|
||||||
|
oMSyntax: 64
|
||||||
|
isSingleValued: TRUE
|
||||||
|
rangeLower: 4
|
||||||
|
cn: takCallsign
|
||||||
|
name: takCallsign
|
||||||
|
lDAPDisplayName: takCallsign
|
||||||
|
description: TAK callsign
|
||||||
|
|
||||||
|
dn: CN=takRole,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
objectClass: top
|
||||||
|
objectClass: attributeSchema
|
||||||
|
attributeID: 1.3.6.1.4.1.34955.1.101
|
||||||
|
attributeSyntax: 2.5.5.12
|
||||||
|
oMSyntax: 64
|
||||||
|
isSingleValued: TRUE
|
||||||
|
cn: takRole
|
||||||
|
name: takRole
|
||||||
|
lDAPDisplayName: takRole
|
||||||
|
description: TAK team role
|
||||||
|
|
||||||
|
dn: CN=takColor,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
objectClass: top
|
||||||
|
objectClass: attributeSchema
|
||||||
|
attributeID: 1.3.6.1.4.1.34955.1.102
|
||||||
|
attributeSyntax: 2.5.5.12
|
||||||
|
oMSyntax: 64
|
||||||
|
isSingleValued: TRUE
|
||||||
|
cn: takColor
|
||||||
|
name: takColor
|
||||||
|
LDAPDisplayName: takColor
|
||||||
|
Description: TAK team color
|
36
lam/docs/schema/tak-Samba4-objectClass.ldif
Normal file
36
lam/docs/schema/tak-Samba4-objectClass.ldif
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#
|
||||||
|
# LDAP schema for LAM TAK functionality
|
||||||
|
#
|
||||||
|
# This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
# Copyright (C) 2025 Roland Gruber
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# OID bases:
|
||||||
|
# 1.3.6.1.4.1.34955 Roland Gruber Softwareentwicklung
|
||||||
|
# 1.3.6.1.4.1.34955.1 attributes
|
||||||
|
# 1.3.6.1.4.1.34955.2 object classes
|
||||||
|
#
|
||||||
|
# Please replace DOMAIN_TOP_DN with your LDAP suffix (e.g. dc=samba4,dc=test).
|
||||||
|
# This file must be installed second.
|
||||||
|
#
|
||||||
|
# Installation: ldbmodify -H /var/lib/samba/private/sam.ldb tak-Samba4-objectClass.ldif --option="dsdb:schema update allowed"=true
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Version: 1
|
||||||
|
# 1: initial release (LAM 9.2)
|
||||||
|
#
|
||||||
|
|
||||||
|
dn: CN=takUser,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
objectClass: top
|
||||||
|
objectClass: classSchema
|
||||||
|
governsID: 1.3.6.1.4.1.34955.2.10
|
||||||
|
cn: takUser
|
||||||
|
lDAPDisplayName: takUser
|
||||||
|
subClassOf: top
|
||||||
|
objectClassCategory: 3
|
||||||
|
mustContain: cn
|
||||||
|
mayContain: takCallsign
|
||||||
|
mayContain: takRole
|
||||||
|
mayContain: takColor
|
||||||
|
description: TAK user
|
||||||
|
possSuperiors: top
|
100
lam/docs/schema/tak-Windows.ldif
Normal file
100
lam/docs/schema/tak-Windows.ldif
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
#
|
||||||
|
# LDAP schema for LAM TAK functionality
|
||||||
|
#
|
||||||
|
# This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
# Copyright (C) 2025 Roland Gruber
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# OID bases:
|
||||||
|
# 1.3.6.1.4.1.34955 Roland Gruber Softwareentwicklung
|
||||||
|
# 1.3.6.1.4.1.34955.1 attributes
|
||||||
|
# 1.3.6.1.4.1.34955.2 object classes
|
||||||
|
#
|
||||||
|
# Please replace DOMAIN_TOP_DN with your LDAP suffix (e.g. dc=windows,dc=test).
|
||||||
|
#
|
||||||
|
# Installation: ldifde -v -i -f tak-Windows.ldif
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# Version: 1
|
||||||
|
# 1: initial release (LAM 9.2)
|
||||||
|
#
|
||||||
|
|
||||||
|
dn: CN=takCallsign,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
changetype: add
|
||||||
|
objectClass: top
|
||||||
|
objectClass: attributeSchema
|
||||||
|
attributeID: 1.3.6.1.4.1.34955.1.100
|
||||||
|
attributeSyntax: 2.5.5.12
|
||||||
|
oMSyntax: 64
|
||||||
|
isSingleValued: TRUE
|
||||||
|
rangeLower: 4
|
||||||
|
cn: takCallsign
|
||||||
|
name: takCallsign
|
||||||
|
lDAPDisplayName: takCallsign
|
||||||
|
description: TAK callsign
|
||||||
|
|
||||||
|
dn: CN=takRole,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
changetype: add
|
||||||
|
objectClass: top
|
||||||
|
objectClass: attributeSchema
|
||||||
|
attributeID: 1.3.6.1.4.1.34955.1.101
|
||||||
|
attributeSyntax: 2.5.5.12
|
||||||
|
oMSyntax: 64
|
||||||
|
isSingleValued: TRUE
|
||||||
|
cn: takRole
|
||||||
|
name: takRole
|
||||||
|
lDAPDisplayName: takRole
|
||||||
|
description: TAK team role
|
||||||
|
|
||||||
|
dn: CN=takColor,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
changetype: add
|
||||||
|
objectClass: top
|
||||||
|
objectClass: attributeSchema
|
||||||
|
attributeID: 1.3.6.1.4.1.34955.1.102
|
||||||
|
attributeSyntax: 2.5.5.12
|
||||||
|
oMSyntax: 64
|
||||||
|
isSingleValued: TRUE
|
||||||
|
cn: takColor
|
||||||
|
name: takColor
|
||||||
|
LDAPDisplayName: takColor
|
||||||
|
Description: TAK team color
|
||||||
|
|
||||||
|
dn:
|
||||||
|
changetype: modify
|
||||||
|
add: schemaUpdateNow
|
||||||
|
schemaUpdateNow: 1
|
||||||
|
-
|
||||||
|
|
||||||
|
dn: CN=takUser,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
changetype: add
|
||||||
|
objectClass: top
|
||||||
|
objectClass: classSchema
|
||||||
|
governsID: 1.3.6.1.4.1.34955.2.10
|
||||||
|
cn: takUser
|
||||||
|
lDAPDisplayName: takUser
|
||||||
|
subClassOf: top
|
||||||
|
objectClassCategory: 3
|
||||||
|
mustContain: cn
|
||||||
|
mayContain: takCallsign
|
||||||
|
mayContain: takRole
|
||||||
|
mayContain: takColor
|
||||||
|
description: TAK user
|
||||||
|
possSuperiors: top
|
||||||
|
|
||||||
|
dn:
|
||||||
|
changetype: modify
|
||||||
|
add: schemaUpdateNow
|
||||||
|
schemaUpdateNow: 1
|
||||||
|
-
|
||||||
|
|
||||||
|
dn: CN=User,CN=Schema,CN=Configuration,DOMAIN_TOP_DN
|
||||||
|
changetype: modify
|
||||||
|
add: auxiliaryClass
|
||||||
|
auxiliaryClass: takUser
|
||||||
|
-
|
||||||
|
|
||||||
|
dn:
|
||||||
|
changetype: modify
|
||||||
|
add: schemaUpdateNow
|
||||||
|
schemaUpdateNow: 1
|
||||||
|
-
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2003 - 2006 Tilo Lutz
|
Copyright (C) 2003 - 2006 Tilo Lutz
|
||||||
2009 - 2024 Roland Gruber
|
2009 - 2025 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -77,6 +77,18 @@ function in_array_ignore_case($needle, $haystack) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if two arrays have the same content.
|
||||||
|
*
|
||||||
|
* @param array $array1 array 1
|
||||||
|
* @param array $array2 array 2
|
||||||
|
* @return bool same content
|
||||||
|
*/
|
||||||
|
function areArrayContentsEqual(array $array1, array $array2): bool {
|
||||||
|
$intersect = array_intersect($array1, $array2);
|
||||||
|
return ((count($array1) === count($array2)) && (count($intersect) === count($array1)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sorts an array in natural order by its keys.
|
* Sorts an array in natural order by its keys.
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,7 +9,7 @@ use LAM\PDF\PDFImage;
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2003 - 2024 Roland Gruber
|
Copyright (C) 2003 - 2025 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -1034,7 +1034,7 @@ abstract class baseModule {
|
||||||
if (!empty($regex)) {
|
if (!empty($regex)) {
|
||||||
$this->checkUploadRegex($regexIDs, $rawAccounts[$position][$ids[$colName]], $message, $position, $errors);
|
$this->checkUploadRegex($regexIDs, $rawAccounts[$position][$ids[$colName]], $message, $position, $errors);
|
||||||
}
|
}
|
||||||
$partialAccounts[$position][$attrName] = trim($rawAccounts[$position][$ids[$colName]]);
|
$partialAccounts[$position][$attrName] = [trim($rawAccounts[$position][$ids[$colName]])];
|
||||||
}
|
}
|
||||||
// multi-value
|
// multi-value
|
||||||
else {
|
else {
|
||||||
|
@ -1799,7 +1799,7 @@ abstract class baseModule {
|
||||||
* @param array $container return value of checkSelfServiceOptions()
|
* @param array $container return value of checkSelfServiceOptions()
|
||||||
* @param String $name attribute name
|
* @param String $name attribute name
|
||||||
* @param array $attributes LDAP attributes
|
* @param array $attributes LDAP attributes
|
||||||
* @param string $fields input fields
|
* @param array $fields input fields
|
||||||
* @param array $readOnlyFields list of read-only fields
|
* @param array $readOnlyFields list of read-only fields
|
||||||
* @param String $validationID validation ID for get_preg()
|
* @param String $validationID validation ID for get_preg()
|
||||||
* @param array $validationMessage validation message data (defaults to $this->messages[$name][0])
|
* @param array $validationMessage validation message data (defaults to $this->messages[$name][0])
|
||||||
|
@ -1822,13 +1822,11 @@ abstract class baseModule {
|
||||||
$container['add'][$ldapAttrName] = [$_POST[$fieldName]];
|
$container['add'][$ldapAttrName] = [$_POST[$fieldName]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elseif ($requiredMessage !== null) {
|
||||||
|
$container['messages'][] = $requiredMessage;
|
||||||
|
}
|
||||||
elseif (isset($attributes[$ldapAttrName])) {
|
elseif (isset($attributes[$ldapAttrName])) {
|
||||||
if ($requiredMessage !== null) {
|
$container['del'][$ldapAttrName] = $attributes[$ldapAttrName];
|
||||||
$container['messages'][] = $requiredMessage;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$container['del'][$ldapAttrName] = $attributes[$ldapAttrName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1954,8 +1952,7 @@ abstract class baseModule {
|
||||||
$container['messages'][] = $requiredMessage;
|
$container['messages'][] = $requiredMessage;
|
||||||
}
|
}
|
||||||
$valuesOld = $attributes[$ldapAttrName] ?? [];
|
$valuesOld = $attributes[$ldapAttrName] ?? [];
|
||||||
$intersect = array_intersect($valuesOld, $valuesNew);
|
if (!areArrayContentsEqual($valuesOld, $valuesNew)) {
|
||||||
if ((count($valuesOld) !== count($valuesNew)) || (count($intersect) !== count($valuesOld))) {
|
|
||||||
$container['mod'][$ldapAttrName] = $valuesNew;
|
$container['mod'][$ldapAttrName] = $valuesNew;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1589,87 +1589,49 @@ class accountContainer {
|
||||||
*/
|
*/
|
||||||
function save_module_attributes($attributes, $orig) {
|
function save_module_attributes($attributes, $orig) {
|
||||||
$return = [];
|
$return = [];
|
||||||
$toadd = [];
|
$toModify = [];
|
||||||
$tomodify = [];
|
$notChanged = [];
|
||||||
$torem = [];
|
// cleanup
|
||||||
$notchanged = [];
|
foreach ($attributes as $name => &$values) {
|
||||||
// get list of all attributes
|
// remove empty values
|
||||||
$attr_names = array_keys($attributes);
|
$values = array_values($values);
|
||||||
$orig_names = array_keys($orig);
|
for ($i = 0; $i < count($values); $i++) {
|
||||||
|
if ($values[$i] === '') {
|
||||||
|
unset($values[$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$values = array_values($values);
|
||||||
|
// remove empty list of values
|
||||||
|
if (sizeof($values) === 0) {
|
||||||
|
unset($attributes[$name]);
|
||||||
|
}
|
||||||
|
}
|
||||||
// find deleted attributes (in $orig but no longer in $attributes)
|
// find deleted attributes (in $orig but no longer in $attributes)
|
||||||
foreach ($orig_names as $value) {
|
foreach ($orig as $name => $value) {
|
||||||
if (!isset($attributes[$value])) {
|
if (!isset($attributes[$name]) || (sizeof($attributes[$name]) === 0)) {
|
||||||
$torem[$value] = $orig[$value];
|
$toModify[$name] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// find changed attributes
|
// find changed attributes
|
||||||
foreach ($attr_names as $name) {
|
foreach ($attributes as $name => $value) {
|
||||||
// find deleted attributes
|
// new attributes
|
||||||
if (isset($orig[$name]) && is_array($orig[$name])) {
|
if (!isset($orig[$name])) {
|
||||||
foreach ($orig[$name] as $value) {
|
$toModify[$name] = $value;
|
||||||
if (is_array($attributes[$name])) {
|
|
||||||
if (!in_array($value, $attributes[$name], true)
|
|
||||||
&& ($value !== null)
|
|
||||||
&& ($value !== '')) {
|
|
||||||
$torem[$name][] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif (($value !== null) && ($value !== '')) {
|
|
||||||
$torem[$name][] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// find new attributes
|
// changed attributes
|
||||||
if (isset($attributes[$name]) && is_array($attributes[$name])) {
|
elseif (!areArrayContentsEqual($value, $orig[$name])) {
|
||||||
foreach ($attributes[$name] as $value) {
|
$toModify[$name] = $value;
|
||||||
if (isset($orig[$name]) && is_array($orig[$name])) {
|
|
||||||
if (!in_array($value, $orig[$name], true)
|
|
||||||
&& ($value !== null)
|
|
||||||
&& ($value !== '')) {
|
|
||||||
$toadd[$name][] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif (($value !== null) && ($value !== '')) {
|
|
||||||
$toadd[$name][] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// find unchanged attributes
|
// unchanged attributes
|
||||||
if (isset($orig[$name]) && is_array($orig[$name]) && is_array($attributes[$name])) {
|
else {
|
||||||
foreach ($attributes[$name] as $value) {
|
$notChanged[$name] = $value;
|
||||||
if (($value !== null) && ($value !== '') && in_array($value, $orig[$name], true)) {
|
|
||||||
$notchanged[$name][] = $value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// create modify with add and remove
|
if ($toModify !== []) {
|
||||||
$attributes2 = array_keys($toadd);
|
$return[$this->dn_orig]['modify'] = $toModify;
|
||||||
for ($i = 0; $i < count($attributes2); $i++) {
|
|
||||||
if (isset($torem[$attributes2[$i]]) && ($toadd[$attributes2[$i]] !== []) && (count($torem[$attributes2[$i]]) > 0)) {
|
|
||||||
// found attribute which should be modified
|
|
||||||
$tomodify[$attributes2[$i]] = $toadd[$attributes2[$i]];
|
|
||||||
// merge unchanged values
|
|
||||||
if (isset($notchanged[$attributes2[$i]])) {
|
|
||||||
$tomodify[$attributes2[$i]] = array_merge($tomodify[$attributes2[$i]], $notchanged[$attributes2[$i]]);
|
|
||||||
unset($notchanged[$attributes2[$i]]);
|
|
||||||
}
|
|
||||||
// remove old add and remove commands
|
|
||||||
unset($toadd[$attributes2[$i]]);
|
|
||||||
unset($torem[$attributes2[$i]]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ($toadd !== []) {
|
if ($notChanged !== []) {
|
||||||
$return[$this->dn_orig]['add'] = $toadd;
|
$return[$this->dn_orig]['notchanged'] = $notChanged;
|
||||||
}
|
|
||||||
if ($torem !== []) {
|
|
||||||
$return[$this->dn_orig]['remove'] = $torem;
|
|
||||||
}
|
|
||||||
if ($tomodify !== []) {
|
|
||||||
$return[$this->dn_orig]['modify'] = $tomodify;
|
|
||||||
}
|
|
||||||
if ($notchanged !== []) {
|
|
||||||
$return[$this->dn_orig]['notchanged'] = $notchanged;
|
|
||||||
}
|
}
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -894,28 +894,6 @@ class inetOrgPerson extends baseModule implements passwordService, AccountStatus
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
$return = parent::save_attributes();
|
$return = parent::save_attributes();
|
||||||
// postalAddress, registeredAddress, facsimileTelephoneNumber and jpegPhoto need special removing
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['remove']['postalAddress'])) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['postalAddress'] = $this->attributes['postalAddress'];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['remove']['postalAddress']);
|
|
||||||
}
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['remove']['registeredAddress'])) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['registeredAddress'] = $this->attributes['registeredAddress'];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['remove']['registeredAddress']);
|
|
||||||
}
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['remove']['facsimileTelephoneNumber'])) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['facsimileTelephoneNumber'] = $this->attributes['facsimileTelephoneNumber'];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['remove']['facsimileTelephoneNumber']);
|
|
||||||
}
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['add']['facsimileTelephoneNumber'])
|
|
||||||
&& isset($this->orig['facsimileTelephoneNumber']) && (count($this->orig['facsimileTelephoneNumber']) > 0)) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['facsimileTelephoneNumber'] = $this->attributes['facsimileTelephoneNumber'];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['add']['facsimileTelephoneNumber']);
|
|
||||||
}
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['remove']['jpegPhoto'])) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['jpegPhoto'] = [];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['remove']['jpegPhoto']);
|
|
||||||
}
|
|
||||||
// add information about clear text password
|
// add information about clear text password
|
||||||
if ($this->clearTextPassword != null) {
|
if ($this->clearTextPassword != null) {
|
||||||
$return[$this->getAccountContainer()->dn_orig]['info']['userPasswordClearText'][0] = $this->clearTextPassword;
|
$return[$this->getAccountContainer()->dn_orig]['info']['userPasswordClearText'][0] = $this->clearTextPassword;
|
||||||
|
@ -2730,19 +2708,19 @@ class inetOrgPerson extends baseModule implements passwordService, AccountStatus
|
||||||
$attributes, $readOnlyFields, false, false, 'givenName');
|
$attributes, $readOnlyFields, false, false, 'givenName');
|
||||||
$this->addSimpleSelfServiceTextField($return, 'lastName', _('Last name'), $fields,
|
$this->addSimpleSelfServiceTextField($return, 'lastName', _('Last name'), $fields,
|
||||||
$attributes, $readOnlyFields, true, false, 'sn');
|
$attributes, $readOnlyFields, true, false, 'sn');
|
||||||
$this->addSimpleSelfServiceTextField($return, 'mail', _('Email address'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'mail', _('Email address'), $fields,
|
||||||
$attributes, $readOnlyFields);
|
$attributes, $readOnlyFields);
|
||||||
$this->addMultiValueSelfServiceTextField($return, 'labeledURI', _('Web site'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'labeledURI', _('Web site'), $fields,
|
||||||
$attributes, $readOnlyFields, false, false, 'labeledURI');
|
$attributes, $readOnlyFields, false, false, 'labeledURI');
|
||||||
$this->addSimpleSelfServiceTextField($return, 'telephoneNumber', _('Telephone number'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'telephoneNumber', _('Telephone number'), $fields,
|
||||||
$attributes, $readOnlyFields, false, false, 'telephoneNumber');
|
$attributes, $readOnlyFields, false, false, 'telephoneNumber');
|
||||||
$this->addSimpleSelfServiceTextField($return, 'homePhone', _('Home telephone number'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'homePhone', _('Home telephone number'), $fields,
|
||||||
$attributes, $readOnlyFields, false, false, 'homePhone');
|
$attributes, $readOnlyFields, false, false, 'homePhone');
|
||||||
$this->addSimpleSelfServiceTextField($return, 'mobile', _('Mobile telephone number'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'mobile', _('Mobile telephone number'), $fields,
|
||||||
$attributes, $readOnlyFields);
|
$attributes, $readOnlyFields);
|
||||||
$this->addSimpleSelfServiceTextField($return, 'faxNumber', _('Fax number'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'faxNumber', _('Fax number'), $fields,
|
||||||
$attributes, $readOnlyFields, false, false, 'facsimileTelephoneNumber');
|
$attributes, $readOnlyFields, false, false, 'facsimileTelephoneNumber');
|
||||||
$this->addSimpleSelfServiceTextField($return, 'pager', _('Pager'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'pager', _('Pager'), $fields,
|
||||||
$attributes, $readOnlyFields);
|
$attributes, $readOnlyFields);
|
||||||
$this->addMultiValueSelfServiceTextField($return, 'street', _('Street'), $fields,
|
$this->addMultiValueSelfServiceTextField($return, 'street', _('Street'), $fields,
|
||||||
$attributes, $readOnlyFields);
|
$attributes, $readOnlyFields);
|
||||||
|
@ -3200,22 +3178,22 @@ class inetOrgPerson extends baseModule implements passwordService, AccountStatus
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'lastName', $attributes, $fields,
|
$this->checkSimpleSelfServiceTextField($return, 'lastName', $attributes, $fields,
|
||||||
$readOnlyFields, 'realname', $this->messages['lastname'][0], $this->messages['lastname'][0],
|
$readOnlyFields, 'realname', $this->messages['lastname'][0], $this->messages['lastname'][0],
|
||||||
'sn');
|
'sn');
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'mail', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'mail', $attributes, $fields,
|
||||||
$readOnlyFields, 'email', $this->messages['mail'][0]);
|
$readOnlyFields, 'email', $this->messages['mail'][0]);
|
||||||
$this->checkMultiValueSelfServiceTextField($return, 'labeledURI', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'labeledURI', $attributes, $fields,
|
||||||
$readOnlyFields, null, null, null, 'labeledURI');
|
$readOnlyFields, null, null, null, 'labeledURI');
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'telephoneNumber', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'telephoneNumber', $attributes, $fields,
|
||||||
$readOnlyFields, 'telephone', $this->messages['telephoneNumber'][0], null,
|
$readOnlyFields, 'telephone', $this->messages['telephoneNumber'][0], null,
|
||||||
'telephoneNumber');
|
'telephoneNumber');
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'homePhone', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'homePhone', $attributes, $fields,
|
||||||
$readOnlyFields, 'telephone', $this->messages['homePhone'][0], null,
|
$readOnlyFields, 'telephone', $this->messages['homePhone'][0], null,
|
||||||
'homePhone');
|
'homePhone');
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'faxNumber', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'faxNumber', $attributes, $fields,
|
||||||
$readOnlyFields, 'telephone', $this->messages['facsimileTelephoneNumber'][0], null,
|
$readOnlyFields, 'telephone', $this->messages['facsimileTelephoneNumber'][0], null,
|
||||||
'facsimileTelephoneNumber');
|
'facsimileTelephoneNumber');
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'mobile', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'mobile', $attributes, $fields,
|
||||||
$readOnlyFields, 'telephone', $this->messages['mobile'][0]);
|
$readOnlyFields, 'telephone', $this->messages['mobile'][0]);
|
||||||
$this->checkSimpleSelfServiceTextField($return, 'pager', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'pager', $attributes, $fields,
|
||||||
$readOnlyFields, 'telephone', $this->messages['pager'][0]);
|
$readOnlyFields, 'telephone', $this->messages['pager'][0]);
|
||||||
$this->checkMultiValueSelfServiceTextField($return, 'street', $attributes, $fields,
|
$this->checkMultiValueSelfServiceTextField($return, 'street', $attributes, $fields,
|
||||||
$readOnlyFields, 'street', $this->messages['street'][0]);
|
$readOnlyFields, 'street', $this->messages['street'][0]);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use LAM\TYPES\ConfiguredType;
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2009 - 2024 Roland Gruber
|
Copyright (C) 2009 - 2025 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -159,32 +159,6 @@ class nisnetgroup extends baseModule {
|
||||||
$this->messages['domain'][0] = ['ERROR', _('Domain name'), _('Domain name is invalid!')];
|
$this->messages['domain'][0] = ['ERROR', _('Domain name'), _('Domain name is invalid!')];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of modifications which have to be made to the LDAP account.
|
|
||||||
*
|
|
||||||
* @return array list of modifications
|
|
||||||
* <br>This function returns an array with 3 entries:
|
|
||||||
* <br>array( DN1 ('add' => array($attr), 'remove' => array($attr), 'modify' => array($attr)), DN2 .... )
|
|
||||||
* <br>DN is the DN to change. It may be possible to change several DNs (e.g. create a new user and add him to some groups via attribute memberUid)
|
|
||||||
* <br>"add" are attributes which have to be added to LDAP entry
|
|
||||||
* <br>"remove" are attributes which have to be removed from LDAP entry
|
|
||||||
* <br>"modify" are attributes which have to been modified in LDAP entry
|
|
||||||
* <br>"info" are values with informational value (e.g. to be used later by pre/postModify actions)
|
|
||||||
*/
|
|
||||||
function save_attributes() {
|
|
||||||
$return = $this->getAccountContainer()->save_module_attributes($this->attributes, $this->orig);
|
|
||||||
// nisNetgroupTriple needs special changing
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['remove']['nisNetgroupTriple'])) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['nisNetgroupTriple'] = $this->attributes['nisNetgroupTriple'];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['remove']['nisNetgroupTriple']);
|
|
||||||
}
|
|
||||||
if (isset($return[$this->getAccountContainer()->dn_orig]['add']['nisNetgroupTriple'])) {
|
|
||||||
$return[$this->getAccountContainer()->dn_orig]['modify']['nisNetgroupTriple'] = $this->attributes['nisNetgroupTriple'];
|
|
||||||
unset($return[$this->getAccountContainer()->dn_orig]['add']['nisNetgroupTriple']);
|
|
||||||
}
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the HTML meta data for the main account page.
|
* Returns the HTML meta data for the main account page.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1382,10 +1382,13 @@ class posixAccount extends baseModule implements passwordService, AccountStatusP
|
||||||
/**
|
/**
|
||||||
* Returns if groups with same name can be created.
|
* Returns if groups with same name can be created.
|
||||||
*
|
*
|
||||||
|
* @param ?string $typeId type ID
|
||||||
* @return bool creation is possible
|
* @return bool creation is possible
|
||||||
*/
|
*/
|
||||||
private function allowsToCreateGroupWithSameName(): bool {
|
private function allowsToCreateGroupWithSameName(?string $typeId = null): bool {
|
||||||
$typeId = $this->getAccountContainer()->get_type()->getId();
|
if ($typeId === null) {
|
||||||
|
$typeId = $this->getAccountContainer()->get_type()->getId();
|
||||||
|
}
|
||||||
if (($this->get_scope() !== 'user')
|
if (($this->get_scope() !== 'user')
|
||||||
|| $this->isBooleanConfigOptionSet('posixAccount_' . $typeId . '_hideCreateGroup')) {
|
|| $this->isBooleanConfigOptionSet('posixAccount_' . $typeId . '_hideCreateGroup')) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -2174,7 +2177,7 @@ class posixAccount extends baseModule implements passwordService, AccountStatusP
|
||||||
if ($this->get_scope() == 'user') {
|
if ($this->get_scope() == 'user') {
|
||||||
// primary Unix group
|
// primary Unix group
|
||||||
$primaryGroups = $groups;
|
$primaryGroups = $groups;
|
||||||
$allowToCreateGroupWithUserName = $this->allowsToCreateGroupWithSameName();
|
$allowToCreateGroupWithUserName = $this->allowsToCreateGroupWithSameName($typeId);
|
||||||
if ($allowToCreateGroupWithUserName) {
|
if ($allowToCreateGroupWithUserName) {
|
||||||
$primaryGroups = [_('Create group with same name') => self::CREATE_GROUP_WITH_SAME_NAME] + $primaryGroups;
|
$primaryGroups = [_('Create group with same name') => self::CREATE_GROUP_WITH_SAME_NAME] + $primaryGroups;
|
||||||
}
|
}
|
||||||
|
|
327
lam/lib/modules/takUser.inc
Normal file
327
lam/lib/modules/takUser.inc
Normal file
|
@ -0,0 +1,327 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
|
||||||
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
|
Copyright (C) 2025 Mark Halliday
|
||||||
|
2025 Roland Gruber
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
use LAM\TYPES\ConfiguredType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the object class "takUser" for users.
|
||||||
|
*
|
||||||
|
* @package modules
|
||||||
|
*
|
||||||
|
* @author Mark Halliday
|
||||||
|
* @author Roland Gruber
|
||||||
|
*/
|
||||||
|
class takUser extends baseModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if this module can manage accounts of the current type, otherwise false.
|
||||||
|
*
|
||||||
|
* @return boolean true if module fits
|
||||||
|
*/
|
||||||
|
public function can_manage() {
|
||||||
|
return $this->get_scope() === 'user';
|
||||||
|
}
|
||||||
|
|
||||||
|
/** possible roles */
|
||||||
|
private const ROLE_TYPES = ['Team Member', 'Team Leader', 'HQ', 'RTO', 'K9', 'Medic', 'Forward Observer', 'Sniper'];
|
||||||
|
|
||||||
|
/** possible colors */
|
||||||
|
private const COLOR_TYPES = ['Blue', 'Brown', 'Cyan', 'Dark Blue', 'Dark Green', 'Green', 'Magenta', 'Maroon', 'Orange', 'Purple', 'Red', 'Teal', 'White', 'Yellow'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function get_metaData() {
|
||||||
|
$return = [];
|
||||||
|
// icon
|
||||||
|
$return['icon'] = 'tak.png';
|
||||||
|
// alias name
|
||||||
|
$return["alias"] = _("TAK");
|
||||||
|
// LDAP filter
|
||||||
|
$return["ldap_filter"] = ['or' => "(objectClass=takUser)"];
|
||||||
|
// RDN attribute
|
||||||
|
$return["RDN"] = ["cn" => "normal"];
|
||||||
|
// module dependencies
|
||||||
|
$return['dependencies'] = ['depends' => [], 'conflicts' => []];
|
||||||
|
// managed object classes
|
||||||
|
$return['objectClasses'] = ['takUser'];
|
||||||
|
// managed attributes
|
||||||
|
$return['attributes'] = ['takcallsign', 'takrole', 'takcolor'
|
||||||
|
];
|
||||||
|
// help Entries
|
||||||
|
$return['help'] = [
|
||||||
|
'takcallsign' => [
|
||||||
|
"Headline" => _("Callsign"), 'attr' => 'takCallsign',
|
||||||
|
"Text" => _("The user's callsign to be displayed to other TAK users. It must be unique.")
|
||||||
|
],
|
||||||
|
'takrole' => [
|
||||||
|
"Headline" => _("Team role"), 'attr' => 'takRole',
|
||||||
|
"Text" => _("The user's role to be displayed to other TAK users.")
|
||||||
|
],
|
||||||
|
'takcolor' => [
|
||||||
|
"Headline" => _("Team color"), 'attr' => 'takColor',
|
||||||
|
"Text" => _("The user's team color to be displayed to other TAK users.")
|
||||||
|
],
|
||||||
|
];
|
||||||
|
// upload fields
|
||||||
|
$return['upload_columns'] = [
|
||||||
|
[
|
||||||
|
'name' => 'takuser_takcallsign',
|
||||||
|
'description' => _('Callsign'),
|
||||||
|
'help' => 'takcallsign',
|
||||||
|
'example' => 'UK-ORG-01',
|
||||||
|
'required' => true,
|
||||||
|
'unique' => true
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'takuser_takrole',
|
||||||
|
'description' => _('Team role'),
|
||||||
|
'help' => 'takrole',
|
||||||
|
'default' => 'Team Member',
|
||||||
|
'values' => implode(", ", self::ROLE_TYPES),
|
||||||
|
'example' => 'Team Member',
|
||||||
|
'required' => true
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'takuser_takcolor',
|
||||||
|
'description' => _('Team color'),
|
||||||
|
'help' => 'takcolor',
|
||||||
|
'default' => 'Cyan',
|
||||||
|
'values' => implode(", ", self::COLOR_TYPES),
|
||||||
|
'example' => 'Cyan',
|
||||||
|
'required' => true
|
||||||
|
],
|
||||||
|
];
|
||||||
|
// available PDF fields
|
||||||
|
$return['PDF_fields'] = [
|
||||||
|
'takcallsign' => _('Callsign'),
|
||||||
|
'takrole' => _('Team role'),
|
||||||
|
'takcolor' => _('Team color'),
|
||||||
|
];
|
||||||
|
// profile options
|
||||||
|
$profileContainer = new htmlResponsiveRow();
|
||||||
|
$profileContainer->add(new htmlResponsiveInputField(_('Callsign'), 'takuser_takcallsign', null, 'takusercallsign'));
|
||||||
|
$profileContainer->add(new htmlResponsiveInputField(_('Team Role'), 'takuser_takrole', null, 'takuserrole'));
|
||||||
|
$profileContainer->add(new htmlResponsiveInputField(_('Team Color'), 'takuser_takcolor', null, 'takusercolor'));
|
||||||
|
$return['profile_options'] = $profileContainer;
|
||||||
|
// self-service field settings
|
||||||
|
$return['selfServiceFieldSettings'] = [
|
||||||
|
'takcallsign' => _('Callsign'),
|
||||||
|
'takrole' => _('Team role'),
|
||||||
|
'takcolor' => _('Team color'),
|
||||||
|
];
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function load_Messages() {
|
||||||
|
$this->messages['takcallsign'][0] = ['ERROR', _('Callsign'), _('Callsign contains invalid characters. Valid characters are: a-z, A-Z, 0-9 and .-_')];
|
||||||
|
$this->messages['takcallsign'][1] = ['ERROR', _('A TAK login with this callsign already exists. Please choose a different callsign.')];
|
||||||
|
$this->messages['takcallsign'][2] = ['ERROR', _('Callsign'), _('This field is required.')];
|
||||||
|
$this->messages['takcallsign'][3] = ['ERROR', _('Account %s:') . ' takuser_takcallsign', _('Callsign contains invalid characters. Valid characters are: a-z, A-Z, 0-9 and .-_')];
|
||||||
|
$this->messages['takrole'][0] = ['ERROR', _('Account %s:') . ' takuser_takrole', _('Please enter a valid option:') . ' ' . implode(', ', self::ROLE_TYPES)];
|
||||||
|
$this->messages['takcolor'][0] = ['ERROR', _('Account %s:') . ' takuser_takcolor', _('Please enter a valid option:') . ' ' . implode(', ', self::COLOR_TYPES)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function display_html_attributes() {
|
||||||
|
$return = new htmlResponsiveRow();
|
||||||
|
// takCallsign
|
||||||
|
$this->addSimpleInputTextField($return, 'takcallsign', _('Callsign'), true);
|
||||||
|
// takRole
|
||||||
|
$takRole = $this->attributes['takrole'][0] ?? '';
|
||||||
|
$return->add(new htmlResponsiveSelect('takrole', self::ROLE_TYPES, [$takRole], _('Team role'), 'takrole'));
|
||||||
|
//takColor
|
||||||
|
$takColor = $this->attributes['takcolor'][0] ?? 'Cyan';
|
||||||
|
$return->add(new htmlResponsiveSelect('takcolor', self::COLOR_TYPES, [$takColor], _('Team color'), 'takcolor'));
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function process_attributes() {
|
||||||
|
$return = [];
|
||||||
|
$this->attributes['takcallsign'][0] = $_POST['takcallsign'];
|
||||||
|
$this->attributes['takrole'][0] = $_POST['takrole'];
|
||||||
|
$this->attributes['takcolor'][0] = $_POST['takcolor'];
|
||||||
|
// check if callsign is filled
|
||||||
|
if ($_POST['takcallsign'] == '') {
|
||||||
|
$return[] = $this->messages['takcallsign'][2];
|
||||||
|
}
|
||||||
|
elseif (!get_preg($_POST['takcallsign'], 'username')) {
|
||||||
|
$return[] = $this->messages['takcallsign'][0];
|
||||||
|
}
|
||||||
|
// check if callsign is unique
|
||||||
|
elseif (empty($this->orig['takcallsign'][0]) || ($this->attributes['takcallsign'][0] !== $this->orig['takcallsign'][0])) {
|
||||||
|
$suffix = $this->getAccountContainer()->get_type()->getSuffix();
|
||||||
|
$search = searchLDAP($suffix, 'takcallsign=' . $_POST['takcallsign'], ['dn']);
|
||||||
|
if (!empty($search)) {
|
||||||
|
$return[] = $this->messages['takcallsign'][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @see baseModule::build_uploadAccounts()
|
||||||
|
*/
|
||||||
|
public function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules, &$type) {
|
||||||
|
$errors = [];
|
||||||
|
for ($i = 0; $i < count($rawAccounts); $i++) {
|
||||||
|
// add object class
|
||||||
|
if (!in_array('takUser', $partialAccounts[$i]['objectClass'])) {
|
||||||
|
$partialAccounts[$i]['objectClass'][] = 'takUser';
|
||||||
|
}
|
||||||
|
$this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'takuser_takcallsign', 'takcallsign', 'username', $this->messages['takcallsign'][3], $errors);
|
||||||
|
$this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'takuser_takrole', 'takrole', null, null, $errors);
|
||||||
|
if (!in_array($partialAccounts[$i]['takrole'][0], self::ROLE_TYPES)) {
|
||||||
|
$errors[] = array_merge($this->messages['takrole'][0], [[$i]]);
|
||||||
|
}
|
||||||
|
$this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'takuser_takcolor', 'takcolor', null, null, $errors);
|
||||||
|
if (!in_array($partialAccounts[$i]['takcolor'][0], self::COLOR_TYPES)) {
|
||||||
|
$errors[] = array_merge($this->messages['takcolor'][0], [[$i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* @see baseModule::get_pdfEntries()
|
||||||
|
*/
|
||||||
|
public function get_pdfEntries($pdfKeys, $typeId) {
|
||||||
|
$return = [];
|
||||||
|
$this->addSimplePDFField($return, 'takcallsign', _('Callsign'));
|
||||||
|
$this->addSimplePDFField($return, 'takrole', _('Team role'));
|
||||||
|
$this->addSimplePDFField($return, 'takcolor', _('Team color'));
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function load_profile($profile) {
|
||||||
|
// profile mappings in meta data
|
||||||
|
parent::load_profile($profile);
|
||||||
|
// special profile options
|
||||||
|
if (!empty($profile['takuser_takcallsign'][0])) {
|
||||||
|
$this->attributes['takcallsign'][0] = $profile['takuser_takcallsign'][0];
|
||||||
|
}
|
||||||
|
if (!empty($profile['takuser_takrole'][0])) {
|
||||||
|
$this->attributes['takrole'][0] = $profile['takuser_takrole'][0];
|
||||||
|
}
|
||||||
|
if (!empty($profile['takuser_takcolor'][0])) {
|
||||||
|
$this->attributes['takcolor'][0] = $profile['takuser_takcolor'][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getSelfServiceOptions($fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
|
||||||
|
$return = [];
|
||||||
|
if ($passwordChangeOnly) {
|
||||||
|
return $return; // only password fields as long no LDAP content can be read
|
||||||
|
}
|
||||||
|
if (!in_array_ignore_case('takUser', $attributes['objectClass'])) {
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
$this->addSimpleSelfServiceTextField($return, 'takcallsign', _('Callsign'), $fields, $attributes, $readOnlyFields, true);
|
||||||
|
if (in_array('takrole', $fields)) {
|
||||||
|
$role = '';
|
||||||
|
if (isset($attributes['takrole'][0])) {
|
||||||
|
$role = $attributes['takrole'][0];
|
||||||
|
}
|
||||||
|
if (in_array('takrole', $readOnlyFields)) {
|
||||||
|
$field = new htmlOutputText($role);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$selected = [];
|
||||||
|
if (!empty($attributes['takrole'][0])) {
|
||||||
|
$selected = [$attributes['takrole'][0]];
|
||||||
|
}
|
||||||
|
$field = new htmlSelect('takUser_takrole', self::ROLE_TYPES, $selected);
|
||||||
|
}
|
||||||
|
$return['takrole'] = new htmlResponsiveRow(
|
||||||
|
new htmlLabel('takUser_takrole', $this->getSelfServiceLabel('takrole', _('Team role'))), $field
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (in_array('takcolor', $fields)) {
|
||||||
|
$color = '';
|
||||||
|
if (isset($attributes['takcolor'][0])) {
|
||||||
|
$color = $attributes['takcolor'][0];
|
||||||
|
}
|
||||||
|
if (in_array('takcolor', $readOnlyFields)) {
|
||||||
|
$field = new htmlOutputText($color);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$selected = [];
|
||||||
|
if (!empty($attributes['takcolor'][0])) {
|
||||||
|
$selected = [$attributes['takcolor'][0]];
|
||||||
|
}
|
||||||
|
$field = new htmlSelect('takUser_takcolor', self::COLOR_TYPES, $selected);
|
||||||
|
}
|
||||||
|
$return['takcolor'] = new htmlResponsiveRow(
|
||||||
|
new htmlLabel('takUser_takcolor', $this->getSelfServiceLabel('takcolor', _('Team color'))), $field
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function checkSelfServiceOptions($fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
|
||||||
|
$return = ['messages' => [], 'add' => [], 'del' => [], 'mod' => [], 'info' => []];
|
||||||
|
if ($passwordChangeOnly) {
|
||||||
|
return $return; // skip processing if only a password change is done
|
||||||
|
}
|
||||||
|
if (!in_array_ignore_case('takUser', $attributes['objectClass'])) {
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
$this->checkSimpleSelfServiceTextField($return, 'takcallsign', $attributes, $fields, $readOnlyFields, 'username', $this->messages['takcallsign'][0], $this->messages['takcallsign'][2]);
|
||||||
|
$this->checkSimpleSelfServiceTextField($return, 'takrole', $attributes, $fields, $readOnlyFields);
|
||||||
|
$this->checkSimpleSelfServiceTextField($return, 'takcolor', $attributes, $fields, $readOnlyFields);
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getListAttributeDescriptions(ConfiguredType $type): array {
|
||||||
|
return [
|
||||||
|
"takcallsign" => _("Callsign"),
|
||||||
|
"takrole" => _("Team role"),
|
||||||
|
"takcolor" => _("Team color"),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ use LamTemporaryFilesManager;
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2004 - 2024 Roland Gruber
|
Copyright (C) 2004 - 2025 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -155,7 +155,7 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) {
|
||||||
$checkcolumns = [];
|
$checkcolumns = [];
|
||||||
$columns = [];
|
$columns = [];
|
||||||
foreach ($uploadColumns as $uploadColumn) {
|
foreach ($uploadColumns as $uploadColumn) {
|
||||||
$columns = array_merge($columns, $uploadColumns);
|
$columns = array_merge($columns, $uploadColumn);
|
||||||
}
|
}
|
||||||
foreach ($columns as $column) {
|
foreach ($columns as $column) {
|
||||||
if (isset($column['required']) && ($column['required'] === true)) {
|
if (isset($column['required']) && ($column['required'] === true)) {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
/*
|
/*
|
||||||
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
||||||
Copyright (C) 2018 - 2024 Roland Gruber
|
Copyright (C) 2018 - 2025 Roland Gruber
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -325,4 +325,13 @@ class AccountTest extends TestCase {
|
||||||
$this->assertFalse(get_preg('ab?c:80', 'hostAndPort'));
|
$this->assertFalse(get_preg('ab?c:80', 'hostAndPort'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testAreArrayContentsEqual() {
|
||||||
|
$this->assertTrue(areArrayContentsEqual([], []));
|
||||||
|
$this->assertFalse(areArrayContentsEqual(['1'], []));
|
||||||
|
$this->assertFalse(areArrayContentsEqual([], ['1']));
|
||||||
|
$this->assertTrue(areArrayContentsEqual(['a', 'b', 'c'], ['c', 'b', 'a']));
|
||||||
|
$this->assertFalse(areArrayContentsEqual(['a', 'b', 'c'], ['a', 'c', 'd']));
|
||||||
|
$this->assertFalse(areArrayContentsEqual(['a', 'b', 'c'], ['a', 'c']));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ parameters:
|
||||||
- '#Call to an undefined method object::.*#'
|
- '#Call to an undefined method object::.*#'
|
||||||
- '#Parameter \#2 \$string of function explode expects string, .* given.#'
|
- '#Parameter \#2 \$string of function explode expects string, .* given.#'
|
||||||
- '#Parameter \#2 \$result of function ldap_.* expects LDAP\\Result, array\|LDAP\\Result given.#'
|
- '#Parameter \#2 \$result of function ldap_.* expects LDAP\\Result, array\|LDAP\\Result given.#'
|
||||||
- '#Cannot access an offset on mixed.#'
|
|
||||||
- '#Cannot access offset .* on mixed.#'
|
- '#Cannot access offset .* on mixed.#'
|
||||||
- '#Cannot access offset .* on array\|int.#'
|
- '#Cannot access offset .* on array\|int.#'
|
||||||
- '#Cannot access an offset on array\|Countable.#'
|
- '#Cannot access an offset on array\|Countable.#'
|
||||||
|
@ -47,4 +46,3 @@ parameters:
|
||||||
- '#Binary operation .* between .* and .* results in an error.#'
|
- '#Binary operation .* between .* and .* results in an error.#'
|
||||||
- '#Parameter \#. .* of (function|method) .* expects .*, mixed given.#'
|
- '#Parameter \#. .* of (function|method) .* expects .*, mixed given.#'
|
||||||
- '#Cannot access property .* on mixed#'
|
- '#Cannot access property .* on mixed#'
|
||||||
- '#Cannot use \+\+ on mixed.#'
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue