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
|
||||
files are licensed under the conditions which you accepted at purchase
|
||||
|
@ -17,6 +17,8 @@ time.
|
|||
* lib/modules/automount.inc
|
||||
* lib/modules/bindDLZ.inc
|
||||
* lib/modules/bindDLZXfr.inc
|
||||
* lib/modules/bindDyndbRecord.inc
|
||||
* lib/modules/bindDyndbZone.inc
|
||||
* lib/modules/customBaseType.inc
|
||||
* lib/modules/customFields.inc
|
||||
* lib/modules/customScripts.inc
|
||||
|
@ -56,6 +58,7 @@ time.
|
|||
* lib/modules/rfc2307bisAutomount.inc
|
||||
* lib/modules/rfc2307bisPosixGroup.inc
|
||||
* lib/modules/selfRegistration.inc
|
||||
* lib/modules/simpleSecurityObject.inc
|
||||
* lib/modules/sudoRole.inc
|
||||
* lib/modules/uidObject.inc
|
||||
* lib/modules/webauthn.inc
|
||||
|
@ -64,6 +67,7 @@ time.
|
|||
* lib/types/alias.inc
|
||||
* lib/types/automountType.inc
|
||||
* lib/types/bind.inc
|
||||
* lib/types/bindDyndbType.inc
|
||||
* lib/types/customType.inc
|
||||
* lib/types/gon.inc
|
||||
* lib/types/kopanoAddressListType.inc
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
June 2025 9.2
|
||||
- TAK support added
|
||||
- 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
|
||||
- Usability improvements (347, 348, 360, 403)
|
||||
|
|
|
@ -17,6 +17,8 @@ time.
|
|||
* lib/modules/automount.inc
|
||||
* lib/modules/bindDLZ.inc
|
||||
* lib/modules/bindDLZXfr.inc
|
||||
* lib/modules/bindDyndbRecord.inc
|
||||
* lib/modules/bindDyndbZone.inc
|
||||
* lib/modules/customBaseType.inc
|
||||
* lib/modules/customFields.inc
|
||||
* lib/modules/customScripts.inc
|
||||
|
@ -56,6 +58,7 @@ time.
|
|||
* lib/modules/rfc2307bisAutomount.inc
|
||||
* lib/modules/rfc2307bisPosixGroup.inc
|
||||
* lib/modules/selfRegistration.inc
|
||||
* lib/modules/simpleSecurityObject.inc
|
||||
* lib/modules/sudoRole.inc
|
||||
* lib/modules/uidObject.inc
|
||||
* lib/modules/webauthn.inc
|
||||
|
@ -64,6 +67,7 @@ time.
|
|||
* lib/types/alias.inc
|
||||
* lib/types/automountType.inc
|
||||
* lib/types/bind.inc
|
||||
* lib/types/bindDyndbType.inc
|
||||
* lib/types/customType.inc
|
||||
* lib/types/gon.inc
|
||||
* lib/types/kopanoAddressListType.inc
|
||||
|
@ -433,7 +437,7 @@ E:
|
|||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
F:
|
||||
F:
|
||||
3-Clause BSD License
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -467,7 +467,7 @@
|
|||
|
||||
<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.</entry>
|
||||
|
@ -486,7 +486,7 @@
|
|||
|
||||
<entry>schema.ldif</entry>
|
||||
|
||||
<entry>part of bind-dyndb-ldap</entry>
|
||||
<entry>Part of bind-dyndb-ldap</entry>
|
||||
|
||||
<entry>LAM Pro only</entry>
|
||||
</row>
|
||||
|
@ -505,7 +505,7 @@
|
|||
|
||||
<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>
|
||||
|
||||
<entry>LAM Pro only</entry>
|
||||
|
@ -821,6 +821,24 @@
|
|||
<entry>LAM Pro only, requires DDS extension on LDAP server
|
||||
side</entry>
|
||||
</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>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
|
|
@ -2510,6 +2510,56 @@ AuthorizedKeysCommandUser root</literallayout>
|
|||
<graphic fileref="images/mod_lastBind3.png"/>
|
||||
</screenshot>
|
||||
</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>
|
||||
|
|
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/)
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
|
|
@ -9,7 +9,7 @@ use LAM\PDF\PDFImage;
|
|||
/*
|
||||
|
||||
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
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1034,7 +1034,7 @@ abstract class baseModule {
|
|||
if (!empty($regex)) {
|
||||
$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
|
||||
else {
|
||||
|
@ -1799,7 +1799,7 @@ abstract class baseModule {
|
|||
* @param array $container return value of checkSelfServiceOptions()
|
||||
* @param String $name attribute name
|
||||
* @param array $attributes LDAP attributes
|
||||
* @param string $fields input fields
|
||||
* @param array $fields input fields
|
||||
* @param array $readOnlyFields list of read-only fields
|
||||
* @param String $validationID validation ID for get_preg()
|
||||
* @param array $validationMessage validation message data (defaults to $this->messages[$name][0])
|
||||
|
@ -1822,13 +1822,11 @@ abstract class baseModule {
|
|||
$container['add'][$ldapAttrName] = [$_POST[$fieldName]];
|
||||
}
|
||||
}
|
||||
elseif ($requiredMessage !== null) {
|
||||
$container['messages'][] = $requiredMessage;
|
||||
}
|
||||
elseif (isset($attributes[$ldapAttrName])) {
|
||||
if ($requiredMessage !== null) {
|
||||
$container['messages'][] = $requiredMessage;
|
||||
}
|
||||
else {
|
||||
$container['del'][$ldapAttrName] = $attributes[$ldapAttrName];
|
||||
}
|
||||
$container['del'][$ldapAttrName] = $attributes[$ldapAttrName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1954,8 +1952,7 @@ abstract class baseModule {
|
|||
$container['messages'][] = $requiredMessage;
|
||||
}
|
||||
$valuesOld = $attributes[$ldapAttrName] ?? [];
|
||||
$intersect = array_intersect($valuesOld, $valuesNew);
|
||||
if ((count($valuesOld) !== count($valuesNew)) || (count($intersect) !== count($valuesOld))) {
|
||||
if (!areArrayContentsEqual($valuesOld, $valuesNew)) {
|
||||
$container['mod'][$ldapAttrName] = $valuesNew;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1589,87 +1589,49 @@ class accountContainer {
|
|||
*/
|
||||
function save_module_attributes($attributes, $orig) {
|
||||
$return = [];
|
||||
$toadd = [];
|
||||
$tomodify = [];
|
||||
$torem = [];
|
||||
$notchanged = [];
|
||||
// get list of all attributes
|
||||
$attr_names = array_keys($attributes);
|
||||
$orig_names = array_keys($orig);
|
||||
$toModify = [];
|
||||
$notChanged = [];
|
||||
// cleanup
|
||||
foreach ($attributes as $name => &$values) {
|
||||
// remove empty values
|
||||
$values = array_values($values);
|
||||
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)
|
||||
foreach ($orig_names as $value) {
|
||||
if (!isset($attributes[$value])) {
|
||||
$torem[$value] = $orig[$value];
|
||||
foreach ($orig as $name => $value) {
|
||||
if (!isset($attributes[$name]) || (sizeof($attributes[$name]) === 0)) {
|
||||
$toModify[$name] = [];
|
||||
}
|
||||
}
|
||||
// find changed attributes
|
||||
foreach ($attr_names as $name) {
|
||||
// find deleted attributes
|
||||
if (isset($orig[$name]) && is_array($orig[$name])) {
|
||||
foreach ($orig[$name] as $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;
|
||||
}
|
||||
}
|
||||
foreach ($attributes as $name => $value) {
|
||||
// new attributes
|
||||
if (!isset($orig[$name])) {
|
||||
$toModify[$name] = $value;
|
||||
}
|
||||
// find new attributes
|
||||
if (isset($attributes[$name]) && is_array($attributes[$name])) {
|
||||
foreach ($attributes[$name] as $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;
|
||||
}
|
||||
}
|
||||
// changed attributes
|
||||
elseif (!areArrayContentsEqual($value, $orig[$name])) {
|
||||
$toModify[$name] = $value;
|
||||
}
|
||||
// find unchanged attributes
|
||||
if (isset($orig[$name]) && is_array($orig[$name]) && is_array($attributes[$name])) {
|
||||
foreach ($attributes[$name] as $value) {
|
||||
if (($value !== null) && ($value !== '') && in_array($value, $orig[$name], true)) {
|
||||
$notchanged[$name][] = $value;
|
||||
}
|
||||
}
|
||||
// unchanged attributes
|
||||
else {
|
||||
$notChanged[$name] = $value;
|
||||
}
|
||||
}
|
||||
// create modify with add and remove
|
||||
$attributes2 = array_keys($toadd);
|
||||
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 ($toModify !== []) {
|
||||
$return[$this->dn_orig]['modify'] = $toModify;
|
||||
}
|
||||
if ($toadd !== []) {
|
||||
$return[$this->dn_orig]['add'] = $toadd;
|
||||
}
|
||||
if ($torem !== []) {
|
||||
$return[$this->dn_orig]['remove'] = $torem;
|
||||
}
|
||||
if ($tomodify !== []) {
|
||||
$return[$this->dn_orig]['modify'] = $tomodify;
|
||||
}
|
||||
if ($notchanged !== []) {
|
||||
$return[$this->dn_orig]['notchanged'] = $notchanged;
|
||||
if ($notChanged !== []) {
|
||||
$return[$this->dn_orig]['notchanged'] = $notChanged;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
|
|
@ -894,28 +894,6 @@ class inetOrgPerson extends baseModule implements passwordService, AccountStatus
|
|||
return [];
|
||||
}
|
||||
$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
|
||||
if ($this->clearTextPassword != null) {
|
||||
$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');
|
||||
$this->addSimpleSelfServiceTextField($return, 'lastName', _('Last name'), $fields,
|
||||
$attributes, $readOnlyFields, true, false, 'sn');
|
||||
$this->addSimpleSelfServiceTextField($return, 'mail', _('Email address'), $fields,
|
||||
$this->addMultiValueSelfServiceTextField($return, 'mail', _('Email address'), $fields,
|
||||
$attributes, $readOnlyFields);
|
||||
$this->addMultiValueSelfServiceTextField($return, 'labeledURI', _('Web site'), $fields,
|
||||
$attributes, $readOnlyFields, false, false, 'labeledURI');
|
||||
$this->addSimpleSelfServiceTextField($return, 'telephoneNumber', _('Telephone number'), $fields,
|
||||
$this->addMultiValueSelfServiceTextField($return, 'telephoneNumber', _('Telephone number'), $fields,
|
||||
$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');
|
||||
$this->addSimpleSelfServiceTextField($return, 'mobile', _('Mobile telephone number'), $fields,
|
||||
$this->addMultiValueSelfServiceTextField($return, 'mobile', _('Mobile telephone number'), $fields,
|
||||
$attributes, $readOnlyFields);
|
||||
$this->addSimpleSelfServiceTextField($return, 'faxNumber', _('Fax number'), $fields,
|
||||
$this->addMultiValueSelfServiceTextField($return, 'faxNumber', _('Fax number'), $fields,
|
||||
$attributes, $readOnlyFields, false, false, 'facsimileTelephoneNumber');
|
||||
$this->addSimpleSelfServiceTextField($return, 'pager', _('Pager'), $fields,
|
||||
$this->addMultiValueSelfServiceTextField($return, 'pager', _('Pager'), $fields,
|
||||
$attributes, $readOnlyFields);
|
||||
$this->addMultiValueSelfServiceTextField($return, 'street', _('Street'), $fields,
|
||||
$attributes, $readOnlyFields);
|
||||
|
@ -3200,22 +3178,22 @@ class inetOrgPerson extends baseModule implements passwordService, AccountStatus
|
|||
$this->checkSimpleSelfServiceTextField($return, 'lastName', $attributes, $fields,
|
||||
$readOnlyFields, 'realname', $this->messages['lastname'][0], $this->messages['lastname'][0],
|
||||
'sn');
|
||||
$this->checkSimpleSelfServiceTextField($return, 'mail', $attributes, $fields,
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'mail', $attributes, $fields,
|
||||
$readOnlyFields, 'email', $this->messages['mail'][0]);
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'labeledURI', $attributes, $fields,
|
||||
$readOnlyFields, null, null, null, 'labeledURI');
|
||||
$this->checkSimpleSelfServiceTextField($return, 'telephoneNumber', $attributes, $fields,
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'telephoneNumber', $attributes, $fields,
|
||||
$readOnlyFields, 'telephone', $this->messages['telephoneNumber'][0], null,
|
||||
'telephoneNumber');
|
||||
$this->checkSimpleSelfServiceTextField($return, 'homePhone', $attributes, $fields,
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'homePhone', $attributes, $fields,
|
||||
$readOnlyFields, 'telephone', $this->messages['homePhone'][0], null,
|
||||
'homePhone');
|
||||
$this->checkSimpleSelfServiceTextField($return, 'faxNumber', $attributes, $fields,
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'faxNumber', $attributes, $fields,
|
||||
$readOnlyFields, 'telephone', $this->messages['facsimileTelephoneNumber'][0], null,
|
||||
'facsimileTelephoneNumber');
|
||||
$this->checkSimpleSelfServiceTextField($return, 'mobile', $attributes, $fields,
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'mobile', $attributes, $fields,
|
||||
$readOnlyFields, 'telephone', $this->messages['mobile'][0]);
|
||||
$this->checkSimpleSelfServiceTextField($return, 'pager', $attributes, $fields,
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'pager', $attributes, $fields,
|
||||
$readOnlyFields, 'telephone', $this->messages['pager'][0]);
|
||||
$this->checkMultiValueSelfServiceTextField($return, 'street', $attributes, $fields,
|
||||
$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/)
|
||||
Copyright (C) 2009 - 2024 Roland Gruber
|
||||
Copyright (C) 2009 - 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
|
||||
|
@ -159,32 +159,6 @@ class nisnetgroup extends baseModule {
|
|||
$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.
|
||||
*
|
||||
|
|
|
@ -1382,10 +1382,13 @@ class posixAccount extends baseModule implements passwordService, AccountStatusP
|
|||
/**
|
||||
* Returns if groups with same name can be created.
|
||||
*
|
||||
* @param ?string $typeId type ID
|
||||
* @return bool creation is possible
|
||||
*/
|
||||
private function allowsToCreateGroupWithSameName(): bool {
|
||||
$typeId = $this->getAccountContainer()->get_type()->getId();
|
||||
private function allowsToCreateGroupWithSameName(?string $typeId = null): bool {
|
||||
if ($typeId === null) {
|
||||
$typeId = $this->getAccountContainer()->get_type()->getId();
|
||||
}
|
||||
if (($this->get_scope() !== 'user')
|
||||
|| $this->isBooleanConfigOptionSet('posixAccount_' . $typeId . '_hideCreateGroup')) {
|
||||
return false;
|
||||
|
@ -2174,7 +2177,7 @@ class posixAccount extends baseModule implements passwordService, AccountStatusP
|
|||
if ($this->get_scope() == 'user') {
|
||||
// primary Unix group
|
||||
$primaryGroups = $groups;
|
||||
$allowToCreateGroupWithUserName = $this->allowsToCreateGroupWithSameName();
|
||||
$allowToCreateGroupWithUserName = $this->allowsToCreateGroupWithSameName($typeId);
|
||||
if ($allowToCreateGroupWithUserName) {
|
||||
$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/)
|
||||
Copyright (C) 2004 - 2024 Roland Gruber
|
||||
Copyright (C) 2004 - 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
|
||||
|
@ -155,7 +155,7 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) {
|
|||
$checkcolumns = [];
|
||||
$columns = [];
|
||||
foreach ($uploadColumns as $uploadColumn) {
|
||||
$columns = array_merge($columns, $uploadColumns);
|
||||
$columns = array_merge($columns, $uploadColumn);
|
||||
}
|
||||
foreach ($columns as $column) {
|
||||
if (isset($column['required']) && ($column['required'] === true)) {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use PHPUnit\Framework\TestCase;
|
||||
/*
|
||||
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
|
||||
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'));
|
||||
}
|
||||
|
||||
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::.*#'
|
||||
- '#Parameter \#2 \$string of function explode expects string, .* 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 array\|int.#'
|
||||
- '#Cannot access an offset on array\|Countable.#'
|
||||
|
@ -47,4 +46,3 @@ parameters:
|
|||
- '#Binary operation .* between .* and .* results in an error.#'
|
||||
- '#Parameter \#. .* of (function|method) .* expects .*, mixed given.#'
|
||||
- '#Cannot access property .* on mixed#'
|
||||
- '#Cannot use \+\+ on mixed.#'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue