Customizing users and groups
Users batch creation
Jahia allows administrators to import users in batch to create local accounts (meaning you don't use an external repository of users like Active Directory or LDAP).
Prepare a CSV file
Your CSV file must be structured as follow: The file must include a header line with at minimum the columns j:nodename (username) and j:password.
You can include any other supported user properties as values, in the desired order. Then, each user to be created must be declared on a different line, with associated values in the correct order.
Example:
j:nodename,j:password,j:firstName,j:lastName
steven,Sseagal666,Steven,Seagal
chucky,TexasRanger,Chuck,Norris
Import users into Jahia
To import users, log yourself into the Jahia Administration Interface (default: http://localhost:8080/administration/) Click on 'Manage users' Click on the button "Batch create users" In the form newly displayed: Type the separator used in your CSV file (default is ',') Select the CSV file by clicking on 'browse' Click on the OK button at the bottom of the screen
DEFAULT PROPERTIES AVAILABLE ON USERS NODES
j:nodename (string)
j:accountLocked (boolean)=false autocreated
j:password (string) indexed=no
j:external (boolean)=false autocreated
j:externalSource (string) nofulltext
j:firstName (string)
j:lastName (string)
j:gender (string,choicelist[resourceBundle]) < male,female,other
j:title (string,choicelist[resourceBundle]) < mister,master,professor,doctor,miss,madam
j:birthDate (date,datepicker)
j:organization (string)
j:function (string)
j:about (string,richtext)
j:email (string) < '^$|[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}'
j:skypeID (string)
j:twitterID (string)
j:facebookID (string)
j:linkedinID (string)
j:picture (weakreference,picker[type='file']) < jnt:file
j:publicProperties (string) multiple
* (string)
User profile
When the user access to his own profile, in live mode he can edit all his information directly on the page without going to edit mode engines or content manager.
This module (located in modules/default/
) mainly use jQuery and Jeditable.
This is a good entry point to have example of how to use in-line edition for editing small properties in live mode.
In this documentation we will show how to make edition of text, richtext, date, file, dropdown properties.
For each of those type of data we use the same principle: a JavaScript function applied to a class that allow the edition of the content when the user clicks on it.
Simple Text
Here the JavaScript example of how to edit a simple text :
<script type="text/javascript">
$(document).ready(function() {
$(".edit").editable(function (value, settings) {
var submitId = $(this).attr('id').replace("_", ":");
var data = {};
data[submitId] = value;
data['jcrMethodToCall'] = 'put';
$.post("${url.base}${currentNode.path}", data, function(result) {
$("#personDisplay").html(result.j_title + " " + result.j_firstName + " " + result.j_lastName);
}, "json");
return(value);
}, {
type : 'text',
onblur : 'ignore',
submit : 'OK',
cancel : 'Cancel',
tooltip : 'Click to edit'
});
});
</script>
In this JavaScript function, we create a data map for handling our form data, we pass a 'jcrMethodToCall' parameter to Jahia to use a put method instead of a post. For the name of the properties to update we get it form the id of the HTML object associated with this edition. When the post is submitted we get the updated node as json data and we update some specific content on the page.
Now the HTML code associated :
<span class="label"><fmt:message key="jnt_user.j_email"/> : </span>
<span id="j_email" class="edit">${fields['j:email']}</span>
Rich Text
For rich text it works the same way, only the type of the editable will change :
<script type="text/javascript">
$(document).ready(function() {
$(".ckeditorEdit").editable(function (value, settings) {
var submitId = $(this).attr('id').replace("_", ":");
var data = {};
data[submitId] = value;
data['jcrMethodToCall'] = 'put';
$.post("${url.base}${currentNode.path}", data, null, "json");
return(value);
}, {
type : 'ckeditor',
onblur : 'ignore',
submit : 'OK',
cancel : 'Cancel',
tooltip : 'Click to edit'
});
});
</script>
Now the HTML for using this CKEditor inline edition :
<div class="ckeditorEdit" id="j_about">${fields['j:about']}</div>
Date Picker
For date, we will use a date picker plugin for jQuery. Here how we use it for Jahia.
<jcr:nodeProperty node="${currentNode}" name="j:birthDate" var="birthDate"/>
<c:if test="${not empty birthDate}">
<fmt:formatDate value="${birthDate.date.time}" pattern="dd/MM/yyyy" var="editBirthDate"/>
</c:if>
<fmt:formatDate value="${now}" pattern="dd/MM/yyyy" var="editNowDate"/>
<script type="text/javascript">
$(document).ready(function() {
$(".dateEdit").editable(function (value, settings) {
var submitId = $(this).attr('id').replace("_", ":");
var data = {};
if (value.match("[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]")) {
var split = value.split("/");
var birth = new Date();
birth.setFullYear(split[2], split[1], split[0]);
var month = "";
if (birth.getMonth() < 10) {
month = "0" + birth.getMonth();
} else month = birth.getMonth();
data[submitId] = birth.getFullYear() + '-' + month + '-' + birth.getDate() + 'T00:00:00';
data['jcrMethodToCall'] = 'put';
$.post("${url.base}${currentNode.path}", data, null, "json");
}
return(value);
}, {
type : 'datepicker',
onblur : 'ignore',
submit : 'OK',
cancel : 'Cancel',
tooltip : 'Click to edit',
datepicker : {
flat: true,
date: '${not empty editBirthDate ? editBirthDate : editNowDate}',
format: 'd/m/Y',
view: 'years',
current: '${not empty editBirthDate ? editBirthDate : editNowDate}',
calendars: 1,
starts: 1 }
});
});
</script>
In this case the internal format for date is day/month/year, when submitting we convert that to an ISO8601 for updating date in Jahia (This is the internal format of the JCR).
HTML usage example :
<jcr:nodeProperty node="${currentNode}" name="j:birthDate" var="birthDate"/>
<c:if test="${not empty birthDate}">
<fmt:formatDate value="${birthDate.date.time}" pattern="dd, MMMM yyyy" var="displayBirthDate"/>
</c:if>
<c:if test="${empty birthDate}">
<jsp:useBean id="now" class="java.util.Date"/>
<fmt:formatDate value="${now}" pattern="dd, MMMM yyyy" var="displayBirthDate"/>
</c:if>
<div class="dateEdit" id="j_birthDate">${displayBirthDate}</div>
DropDown List
We will now see how to use the choicelist initializer mechanism to allow creation of custom static drop down list (as opposed to dynamic one that will load data from the server on demand)
<jcr:propertyInitializers node="${currentNode}" name="j:title" var="titleInit"/>
<script type="text/javascript">
var titleMap = "{<c:forEach items="${titleInit}" varStatus="status" var="title"><c:if test="${status.index > 0}">,</c:if>'${title.value.string}':'${title.displayName}'</c:forEach>}";
$(document).ready(function() {
$(".titleEdit").editable(function (value, settings) {
var submitId = $(this).attr('id').replace("_", ":");
var data = {};
data[submitId] = value;
data['jcrMethodToCall'] = 'put';
$.post("${url.base}${currentNode.path}", data, null, "json");
return eval("values="+titleMap)[value];
}, {
type : 'select',
data : titleMap,
onblur : 'ignore',
submit : 'OK',
cancel : 'Cancel',
tooltip : 'Click to edit'
});
});
</script>
The tag <jcr:propertyInitializers/> store the list of ChoiceListValue object associated with the property to the specified var. We iterate over the list to create a JavaScript map that will be used for initializing our data for the dropdown list.
HTML usage example :
<div class="titleEdit" id="j_title">
<jcr:nodePropertyRenderer node="${currentNode}" name="j:title" renderer="resourceBundle"/>
</div>
Ajax Upload
Now we will see how to upload a file in live mode using ajax requests.
This is a two-phase submit, first we upload the selected file to the user files folder, then we get back the id of the file and we associate it to the property we want. Here the code doing that :
<script type="text/javascript">
$(document).ready(function() {
$(".imageEdit").editable('${url.base}${currentNode.path}', {
type : 'ajaxupload',
onblur : 'ignore',
submit : 'OK',
cancel : 'Cancel',
tooltip : 'Click to edit',
callback : function (data, status) {
uploadedImageCallback(data, status);
}
});
function uploadedImageCallback(data, status) {
var datas = {};
datas['j:picture'] = data.uuids[0];
datas['jcrMethodToCall'] = 'put';
$.post('${url.base}${currentNode.path}', datas, function(result) {
var input = $('<div class="itemImage itemImageRight"><img src="' + result.j_picture + '" width="60" height="60"/></div>');
$("#portrait").html(input);
}, "json");
}
});
</script>
We see that the ajaxupload editable allow to define a callback with the data from the result of the post. We use those datas (list of uuids) to associate the newly created file with our profile j:picture property. Once associated in the json for the j:picture property we have the url associated instead of the uuid of the reference.
HTML usage example :
<div class="image imageEdit" id="portrait">
<div class="itemImage itemImageRight"><jcr:nodeProperty var="picture" node="${currentNode}" name="j:picture"/>
<c:if test="${not empty picture}">
<img src="${picture.node.url}" alt="${person}" width="60" height="60"/>
</c:if>
</div>
</div>
Access User Properties From My Templates
In your templates, the user as a JahiaUser object is available directly under the renderContext object.
// Display username
${renderContext.user.username}
// Display user firstname
${renderContext.user.properties['j:firstName']}
Users extension
General info about users and users data
All users nodes are found under the /users folder, they are split following some customizable rules.
By default we split them into 3 subfolders, to ensure scalability of the platform.
Under a user node, you can store anything you want (any properties, any sub-nodes).
All properties you will add to users are not displayed in their profiles. If you want the users to manage those properties through their profiles pages you, you will have to customize the profiles templates (through the studio/jsp files).
The user nodes are not for storing some navigational history or heavy data sets requiring a huge continuous write activity, they must be reserved to store contents/preferences/properties related to a user.
To store some behavioral data about users you will have to implement some Apache Camel log listeners like the Page Hit module (available on the Jahia Forge as a code sample) to store data in an asynchronous way in a DB/Hadoop (FS or DB)/other type of storage. See the Jahia/Apache Camel documentation.
If you have a limited number of data (less than 1000 nodes) per user you want to use for personalization then you can store them under subnodes of the user.
Differences between Jahia Users / LDAP Users
From Jahia side there are not many differences between LDAP users and Jahia users, you can store your custom properties/nodes in both of them. In fact all users of the system will have it own sub node, that it came from Jahia or from an external system like LDAP.
The only difference is that in the case of the LDAP users, all properties are not coming from Jahia nor from LDAP but are a merge of those two sources.
LDAP Connector
Versions 7.1 and 7.2
This module provides LDAP provider implementations for the user and user groups. Jahia supports multiple LDAP providers to be used simultaneously to achieve better flexibility and data aggregation.
Since version 7.1, LDAP user and group providers can be configured using the administration UI under Server settings / Users and Roles / User and group providers. The UI provides a convenient way to add, remove, start or suspend providers and also adjust their configuration.
Various configuration properties can be provided/adjusted directly in the provider edit screen:
Internally the OSGi ConfigurationAdmin service is used to store the user and group LDAP provider configuration. Thanks to this, hot deploy and editing of your configuration can be done.
Please, refere to the property reference for more details.
User provider properties reference
The following LDAP properties can be specified to customize the user provider configuration:
- Connection and authentication parameters
Key Default value Description url
<none>
The LDAP connection URL, e.g. ldap://127.0.0.1:389/
public.bind.dn
<none>
This is the user on the LDAP server permitted to search the LDAP directory within the defined search base. public.bind.password
<none>
The password used to authenticate searches in LDAP directory target.site
<none>
[Optional] Set a site key to mount the provider on a site authentification.mode
simple
LDAP directory authentication type context.factory
com.sun.jndi.ldap.LdapCtxFactory
The implementation class for context factory to use ldap.connect.pool
apache-commons
Type of pool to use: ldap, apache-commons, or none. See next sections for pool type-specific parameters. - Connection parameters for native Java ldap pool
Key Default value Description ldap.connect.pool.debug
<none>
A string that indicates the level of debug output to produce. Valid values are "fine" (trace connection creation and removal) and "all" (all debugging information). ldap.connect.pool.initSize
1
The string representation of an integer that represents the number of connections per connection identity to create when initially creating a connection for the identity. ldap.connect.pool.maxSize
<none>
The string representation of an integer that represents the maximum number of connections per connection identity that can be maintained concurrently. ldap.connect.pool.prefSize
<none>
The string representation of an integer that represents the preferred number of connections per connection identity that should be maintained concurrently. ldap.connect.pool.timeout
<none>
The string representation of an integer that represents the number of milliseconds that an idle connection may remain in the pool without being closed and removed from the pool. - Connection parameters for apache-commons pool
Key Default value Description ldap.connect.pool.maxActive
8
The maximum number of active connections of each type (read-only|read-write) that can be allocated from this pool at the same time, or non-positive for no limit. ldap.connect.pool.maxTotal
-1
The overall maximum number of active connections (for all types) that can be allocated from this pool at the same time, or non-positive for no limit. ldap.connect.pool.maxIdle
8
The maximum number of active connections of each type (read-only|read-write) that can remain idle in the pool, without extra ones being released, or non-positive for no limit. ldap.connect.pool.minIdle
0
The minimum number of active connections of each type (read-only|read-write) that can remain idle in the pool, without extra ones being created, or zero to create none. ldap.connect.pool.maxWait
-1
The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or non-positive to wait indefinitely. ldap.connect.pool.whenExhaustedAction
BLOCK
Specifies the behavior when the pool is exhausted.
- The FAIL option will throw aNoSuchElementException when the pool is exhausted.
- The BLOCK option will wait until a new object is available. If max-wait is positive a NoSuchElementException is thrown if no new object is available after the max-wait time expires.
- The GROW option will create and return a new object (essentially makingmax-active meaningless).
ldap.connect.pool.testOnBorrow
false
The indication of whether objects will be validated before being borrowed from the pool. If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made. ldap.connect.pool.testOnReturn
false
The indication of whether objects will be validated before being returned to the pool. ldap.connect.pool.testWhileIdle
false
The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to validate, it will be dropped from the pool. ldap.connect.pool.timeBetweenEvictionRunsMillis
-1
The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle object evictor thread will be run. ldap.connect.pool.numTestsPerEvictionRun
3
The number of objects to examine during each run of the idle object evictor thread (if any). ldap.connect.pool.minEvictableIdleTimeMillis
1000 * 60 * 30
The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle object evictor (if any). - Search parameters
Key Default value Description uid.search.name
<none>
The search base that defines which part of the LDAP directory tree to search, e.g. dc=jahia,dc=com
To improve performance when retrieving the members of groups it is advisable to have a different base between user and group search.uid.search.attribute
cn
The name of the attribute that will be used as a user key. search.objectclass
person
The objectClass
value for a user objectsearch.wildcards.attributes
ou, cn, o, c, mail, uid, uniqueIdentifier, givenName, sn, dn
A list of attributes to use for wildcard searches such as *=*test* search.countlimit
100
The number of entries to limit search results too. If the LDAP user search returns more matching entries than specified with this parameter, the first search.countlimit will be returned only. search.attribute.inDn
false
If set to true, signal that the users and groups ids are contained in the dn. Useful to improve the performance when lookup the members. user.search.filter
<none>
A pre-defined filter which will be applied additionally to all user searches and lookups, effectively filtering non-matching users out. This option is available since LDAP module version 3.0.6 (DX 7.1.2.3) and 3.1.1 (DX 7.2.0.2). - Attribute mapping parameters - defines a mapping between Jahia's
jnt:user
node properties and the corresponding LDAP object attributes.Key Default value Description user.j:firstName.attribute.map
givenName
First name user.j:lastName.attribute.map
sn
Second name user.j:email.attribute.map
mail
User's e-mail address user.j:organization.attribute.map
ou
The name of the organization Additional attribute mappings can be specified, using the following pattern for the entry key:
user.<jahia-user-property-name>.attribute.map
and the name of the corresponding LDAP object attribute as the value.
User group provider properties reference
The following LDAP properties can be specified to customize the group provider configuration:
- Connection and authentication parameters
Key Default value Description url
<none>
The LDAP connection URL, e.g. ldap://127.0.0.1:389/
public.bind.dn
<none>
This is the user on the LDAP server permitted to search the LDAP directory within the defined search base. public.bind.password
<none>
The password used to authenticate searches in LDAP directory target.site
<none>
[Optional] Set a site key to mount the provider on a site authentification.mode
simple
LDAP directory authentication type context.factory
com.sun.jndi.ldap.LdapCtxFactory
The implementation class for context factory to use ldap.connect.pool
apache-commons
Type of pool to use: LDAP, apache-commons, or none. See above sections for pool type-specific parameters. - Search and membership parameters
Key Default value Description preload
false
If set to true
forces the reading of all group members when a group is retrieved. Otherwise, group members will be read when the first request for user membership will be madesearch.countlimit
100
The number of entries to limit search results too. If the LDAP user search returns more matching entries than specified with this parameter, the first search.countlimit
will be returned only.refferal
ignore
Specifies how referrals encountered by the service provider are to be processed. Possible values are follow
- follow referrals automatically,ignore
- ignore referrals,throw
- throwReferralException
when a referral is encounteredad.range.step
0
Handle Active Directory range searches when retrieving group members. If set to 0
all members are retrieved with a single search. If set e.g. to100
, searches likerange=0-100
,range=101-200
,range=201-300
etc. are used to retrieve all members iteratively.search.name
<none>
The search base that defines which part of the LDAP directory tree to search, e.g. dc=jahia,dc=com
To improve performance when retrieving the members of groups it is advisable to have a different base between user and group search.search.attribute
cn
The name of the attribute that will be used as a user key. search.objectclass
groupOfUniqueNames
The objectClass
value for a group objectsearch.wildcards.attributes
cn,description,uniqueMember
A list of attributes to use for wildcard searches such as *=*test* members.attribute
uniqueMember
The name of the LDAP group object attribute to retrieve membership from dynamic.enabled
false
Set to true if you want to use the dynamic groups dynamic.search.objectclass
groupOfURLs
The name of the LDAP group object attribute to retrieve dynamic membership from dynamic.members.attribute
memberurl
The name of the LDAP group object attribute to retrieve dynamic membership from canGroupContainSubGroups
false
Set to true to enable support for nested (hierarchical) groups, i.e. where a group could have other groups as members. group.search.filter
<none>
A pre-defined filter which will be applied additionally to all group searches and lookups, effectively filtering non-matching groups out. This option is available since LDAP module version 3.0.6 (DX 7.1.2.3) and 3.1.1 (DX 7.2.0.2). - Attribute mapping parameters - defines a mapping between Jahia's
jnt:group
node properties and the corresponding LDAP object attributes.Key Default value Description group.groupname.attribute.map
cn
Group name group.description.attribute.map
description
Description Additional attribute mappings can be specified, using the following pattern for the entry key: "
group.<jahia-group-property-name>.attribute.map
" and the name of the corresponding LDAP object attribute as the value.
Legacy versions 6.5/6.6/7.0
This module provides LDAP provider implementations for the user and user groups. From version 6.5 up Jahia supports multiple LDAP providers to be used simultaneously to achieve better flexibility and data aggregation.
6.5/6.6
The following steps show how to enable and configure in version 6.5 or 6.6 the user and group LDAP providers, by declaring them in a custom Jahia module.
- Create the following folder structure for your module:
META-INF | + spring | | - users-ldap.xml | | - groups-ldap.xml | - MANIFEST.MF
- The content of the
MANIFEST.MF
file should include three mandatory attributes:... depends: Jahia LDAP connector package-name: My Custom LDAP Provider root-folder: my-custom-ldap-provider ...
depends
attribute defines a dependency to the Jahia LDAP connector module (this module).package-name
specifies your module IDroot-folder
contains the name of the folder, the content of the module will be extracted into (a sub-folder of the/modules
folder).All other attributes in
MANIFEST.MF
file are optional. - LDAP user provide configuration in
users-ldap.xml
The file contains a Spring bean definition for the user provider as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean parent="JahiaUserManagerLDAPProvider"> <property name="ldapProperties"> <map> <entry key="url" value="ldap://127.0.0.1:389/"/> <entry key="public.bind.dn" value=""/> <entry key="public.bind.password" value=""/> <entry key="uid.search.name" value="dc=jahia"/> </map> </property> </bean> </beans>
The bean has as
JahiaUserManagerLDAPProvider
its parent and should override at least the propertyldapProperties
to configure connector and LDAP attribute mapping. Default LDAP parameter values are defined in parent and can be overridden in the mapldapProperties
. See property reference for more details.In case multiple LDAP user providers are used, additionally two properties need to be provided to specify a unique provider key and a priority (lookup sequence):
... <bean parent="JahiaUserManagerLDAPProvider"> <property name="key" value="myldap"/> <property name="priority" value="2"/> ... </bean> ...
The file
users-ldap.xml
name is arbitrary and the file itself can be omitted if no LDAP user provider is needed. - LDAP user group provide a configuration in
groups-ldap.xml
The file contains a Spring bean definition for the user group provider as follows:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean parent="JahiaGroupManagerLDAPProvider"> <property name="ldapProperties"> <map> <entry key="url" value="ldap://127.0.0.1:389/"/> <entry key="public.bind.dn" value=""/> <entry key="public.bind.password" value=""/> <entry key="search.name" value="dc=jahia"/> </map> </property> </bean> </beans>
The bean has
JahiaGroupManagerLDAPProvider
as its parent and should override at least theldapProperties
property to properly configure connector and LDAP attribute mapping. Default LDAP parameter values are defined in parent and can be overridden in theldapProperties
map. See property reference for more details.In case multiple LDAP user group providers are used, additionally two properties need to be provided to specify a unique provider key and a priority (lookup sequence):
... <bean parent="JahiaGroupManagerLDAPProvider"> <property name="key" value="myldap"/> <property name="priority" value="2"/> ... </bean> ...
The
groups-ldap.xml
file name is arbitrary and the file itself can be omitted, if no LDAP user provider is needed. - Zip the content of your module into a file with
.war
, e.g.my-custom-ldap-provider.war
- Copy the module WAR file into the
WEB-INF/var/shared_module
folder of your server (all cluster nodes) - If the module hot deployment is enabled the providers will be registered automatically. Otherwise a server restart is required for a module to be deployed and providers to be registered.
7.0+
Since version 7, OSGi ConfigurationAdmin service is used to declare user and group LDAP providers. Thanks to this, hot deploy and editing of your configuration can be done.
You just need to create a configuration file in the digital-factory-data/karaf/etc/ directory (for 7.0.0.0/7.0.0.1 the /WEB-INF/var/modules/ directory of your Jahia webapp).
This file should respect the following name format: org.jahia.services.usermanager.ldap-config
.cfg
The config
part can be replaced by another configuration name, if you need to create several LDAP configurations. Starting from DX 7.2.0.0, configuration files should not be placed in /modules anymore, and rather moved in the karaf/etc folder.
This file is a regular properties file. It contains properties for one user and/or one group LDAP provider(s).
User-specific and group-specific properties keys respectively need to be prefixed by user.
and group.
.
To avoid repeating shared properties like connection and authentication parameters, you can keep only one without prefix.
Notice that if you want to declare only a user or only a group provider, all the properties keys in the configuration file should start with the corresponding prefix.
See property reference for more details.
Here is an example of a LDAP configuration file content:
user.uid.search.name:dc=jahia,dc=com
group.search.name:dc=jahia,dc=com
public.bind.password:ldapadmin
public.bind.dn:cn=admin,dc=jahia,dc=com
url=ldap://myldapserver:389/
A LDAP configuration file can be created or edited without restarting your application server.
Existing configurations can also be edited from the Jahia Felix Web Console Configuration accessible in the tools at the following URL:
<your_server>/tools/osgi/console/configMgr
User provider properties reference
The following LDAP properties can be specified in the ldapProperties
map to customize the user provider configuration:
- Connection and authentication parameters
Key Default value Description url
<none>
The LDAP connection URL, e.g. ldap://127.0.0.1:389/
public.bind.dn
<none>
This is the user on the LDAP server permitted to search the LDAP directory within the defined search base. public.bind.password
<none>
The password, used to authenticate searches in LDAP directory target.site
<none>
[Optional] Set a site key to mount the provider on a site authentification.mode
simple
LDAP directory authentication type context.factory
com.sun.jndi.ldap.LdapCtxFactory
The implementation class for context factory to use ldap.connect.pool
true
Enables/disables connection pooling ldap.connect.timeout
5000
When connection pooling has been enabled and no pooled connection is available, the client application will block, waiting for an available connection. Setting this timeout value will specify how long to wait for a pooled connection (in milliseconds). If you omit this property, the application will wait indefinitely. See connection pooling for details. search.countlimit
100
The number of entries to limit search results to. If the LDAP user search returns more matching entries than specified with this parameter, the first search.countlimit
will be returned only. - Search parameters
Key Default value Description uid.search.name
<none>
The search base that defines which part of the LDAP directory tree to search, e.g. dc=jahia,dc=com
uid.search.attribute
cn
The name of the attribute that will be used as a user key. search.objectclass
person
The objectClass
value for a user objectsearch.wildcards.attributes
ou, cn, o, c, mail, uid, uniqueIdentifier, givenName, sn, dn
A list of attributes to use for wildcard searches such as *=*test* - Attribute mapping parameters - defines a mapping between Jahia's
jnt:user
node properties and the corresponding LDAP object attributes.Key Default value Description j:firstName.attribute.map
givenName
First name j:lastName.attribute.map
sn
Second name j:email.attribute.map
mail
User's e-mail address j:organization.attribute.map
ou
The name of the organization Additional attribute mappings can be specified, using the following pattern for the entry key: "
<jahia-user-property-name>.attribute.map
" and the name of the corresponding LDAP object attribute as the value.
User group provider properties reference
The following LDAP properties can be specified in the ldapProperties
map to customize the group provider configuration:
- Connection and authentication parameters
Key Default value Description url
<none>
The LDAP connection URL, e.g. ldap://127.0.0.1:389/
public.bind.dn
<none>
This is the user on the LDAP server permitted to search the LDAP directory within the defined search base. public.bind.password
<none>
The password used to authenticate searches in LDAP directory target.site
<none>
[Optional] Set a site key to mount the provider on a site authentification.mode
simple
LDAP directory authentication type context.factory
com.sun.jndi.ldap.LdapCtxFactory
The implementation class for context factory to use ldap.connect.pool
true
Enables/disables connection pooling ldap.connect.timeout
5000
When connection pooling has been enabled and no pooled connection is available, the client application will block, waiting for an available connection. Setting this timeout value will specify how long to wait for a pooled connection (in milliseconds). If you omit this property, the application will wait indefinitely. See connection pooling for details. - Search and membership parameters
Key Default value Description preload
false
If set to true
forces the reading of all group members when a group is retrieved. Otherwise, group members will be read when the first request for user membership will be madesearch.countlimit
100
The number of entries to limit search results too. If the LDAP user search returns more matching entries than specified with this parameter, the first search.countlimit
will be returned only.refferal
ignore
Specifies how referrals encountered by the service provider are to be processed. Possible values are follow
- follow referrals automatically,ignore
- ignore referrals,throw
- throwReferralException
when a referral is encounteredad.range.step
0
Handle Active Directory range searches when retrieving group members. If set to 0
all members are retrieved with a single search. If set e.g. to100
, searches likerange=0-100
,range=101-200
,range=201-300
etc. are used to retrieve all members iteratively.search.name
<none>
The search base that defines which part of the LDAP directory tree to search, e.g. dc=jahia,dc=com
search.attribute
cn
The name of the attribute that will be used as a user key. search.objectclass
groupOfUniqueNames
The objectClass
value for a group objectsearch.wildcards.attributes
cn,description,uniqueMember
A list of attributes to use for wildcard searches such as *=*test* members.attribute
uniqueMember
The name of the LDAP group object attribute to retrieve membership from dynamic.search.objectclass
groupOfURLs
The name of the LDAP group object attribute to retrieve dynamic membership from dynamic.members.attribute
memberurl
The name of the LDAP group object attribute to retrieve dynamic membership from - Attribute mapping parameters - defines a mapping between Jahia's
jnt:user
node properties and the corresponding LDAP object attributes.Key Default value Description groupname.attribute.map
cn
Group name description.attribute.map
description
Description Additional attribute mappings can be specified, using the following pattern for the entry key: "
<jahia-group-property-name>.attribute.map
" and the name of the corresponding LDAP object attribute as the value.
Customizing user dashboard
The user dashboard is defined as a wrapper for the user object jnt:user
. This wrapper is editable in the studio.
By default, we use a tabular list where each tab is, in fact, displaying a specific view of the jnt:user
object.
You can define a new view for the type jnt:user in your module and then add a new tab in the wrapper to render it.
As an example, we will show you how the module docspace define a view for the user listing all the docspaces he can access, the path of the template is (docspace/jnt_user/html/user.mydocspaces.jsp
).
<template:addResources type="css" resources="docspace.css"/>
<template:addResources type="javascript" resources="jquery.min.js"/>
<div id="${currentNode.identifier}">
<jcr:sql var="result"
sql="select * from [jnt:folder] as file order by file.[jcr:lastModified] desc"/>
<c:set var="currentList" value="${result.nodes}" scope="request"/>
<c:set var="listTotalSize" value="${functions:length(result.nodes)}" scope="request"/>
<c:choose>
<c:when test="${empty param.pagesize}">
<c:set var="pageSize" value="40"/>
</c:when>
<c:otherwise>
<c:set var="pageSize" value="${param.pagesize}"/>
</c:otherwise>
</c:choose>
<template:initPager totalSize="${listTotalSize}" pageSize="${pageSize}" id="${currentNode.identifier}"/>
<ul class="docspacelist">
<c:forEach items="${currentList}" var="subchild" varStatus="status" begin="${begin}" end="${end}">
<c:if test="${jcr:hasPermission(subchild, 'jcr:write') and (not empty jcr:getParentOfType(subchild, 'jnt:page'))}">
<li>
<a class="adocspace" href="${url.basePreview}${subchild.path}.html"
title="${subchild.name}">${functions:abbreviate(subchild.name,20,30,'...')}</a>
<span><fmt:message key="label.lastModif"/>: <fmt:formatDate
value="${subchild.properties['jcr:lastModified'].date.time}" dateStyle="short"
type="both"/></span>
</li>
</c:if>
</c:forEach>
</ul>
<template:displayPagination nbItemsList="5,10,20,40,60,80,100,200"/>
<template:removePager id="${currentNode.identifier}"/>
</div>
Users registration
This module declares a component which, once inserted in a page, present a form to users to allow self-registration into the system;
It is possible to notify the relevant administrator(s) that a new user has registered (by email) * The landing page (where the user is redirected after the form is submitted) need to be set.
By default, the following fields are displayed and marked as "mandatory" (this, of course, can be customized into the definition)
- First Name
- Last Name
- Username
- Password
The form can be extended at will, with any additional user property.
<input type="text" name="property_name" id="property_name" value="" tabindex="xx"/>
Registering a user triggers an automatic email to the administrator of the platform, and a welcome email to the newly registered user.
On the server, the Jahia folder User registration folder / mail / templates / contains the template used for these automatic notifications: this template accepts HTML and can be customized easily.
Users and groups service modifications 7.1
Main changes
org.jahia.services.usermanager.JahiaUser and org.jahia.services.usermanager.JahiaGroup most usages have been replaced by JCR node decorators, respectively org.jahia.services.content.decorator.JCRUserNode and org.jahia.services.content.decorator.JCRGroupNode.
The session current user and workflow participants are still JahiaUser
.
JahiaUser
and JahiaGroup
are used as well in the new User and Group Providers.
User and group keys are now the node path instead of “{provider}name”.
Something to take care of in the JSPs is that now we manipulate JCR nodes, user properties are JCR properties instead of just String values.
Details
Services
- In the
org.jahia.services.usermanager.JahiaUserManagerService
class, all methods that previously returned or took in argument aJahiaUser
(lookup, user creation/edition, etc) now manipulateJCRUserNode
objects. - In the
org.jahia.services.usermanager.JahiaGroupManagerService
class, all methods that previously returned or took in argument aJahiaGroup
(lookup, group creation/edition, etc) now manipulateJCRGroupNode
objects.
TLDs
uiComponents:userList
anduiComponents:groupList
tags have been removed (they were deprecated)functions:memberOf
andfunctions:notMemberOf
need theRenderContext
as an additional argumentfunctions:lookupUser
(deprecated) /user:lookupUser
returnsJCRUserNode
instead ofJahiaUser
functions:displayName
(deprecated) /user:displayName
takes aJCRNodeWrapper
instead of aPrincipal
functions:fullName
(deprecated) /user:fullName
takes aJCRNodeWrapper
instead of aPrincipal
user:formatUserValueOption
takes aJCRNodeWrapper
instead of aPrincipal
user:formatUserTextOption
takes aJCRNodeWrapper
instead of aPrincipal
user:isReadOnlyProvider
takes aJCRNodeWrapper
instead of aPrincipal
Mail templates
user
andcurrentUser
variables are nowJCRUserNode
instead ofJahiaUser
Removed and deprecated classes
The following classes have been removed:
org.jahia.services.usermanager.jcr.JCRPrincipal
org.jahia.services.usermanager.jcr.JCRUser
org.jahia.services.usermanager.jcr.JCRGroup
org.jahia.services.usermanager.jcr.JCRUserManagerProvider
org.jahia.services.usermanager.jcr.JCRGroupManagerProvider
are now deprecated. They’ve been kept to register legacy providers using the User and Group Bridge Provider.
New LDAP provider
The new ldap provider, support all the previous parameters available from the conf property file.
Here is the documentation for the old parameters:
http://www.jahia.com/fr/home/resources/developers-techwiki/users-and-groups/ldap-connector.html
In addition, some new parameters are available, to better handle performance/cache/… and other configuration setters.
Here is the list of all the new parameters:
connection pool configuration:
- Since we used spring ldap it’s possible to use different pool system
- The choice is between “ldap”, “apache-commons”, “none”
- ldap: is the default ldap connection pool
- apache-commons: is the more configurable pool, and it's brought by spring ldap
- none: to specify that we don’t want a pooled connection
here is the configurations related to this pools:
key | default | desc |
---|---|---|
ldap.connect.pool | apache-commons | Type of pool to use : ldap, apache-commons, or none |
Connection parameters for native ldap pool :
key | default | desc |
---|---|---|
ldap.connect.pool.debug | A string that indicates the level of debug output to produce. Valid values are "fine" (trace connection creation and removal) and "all" (all debugging information). | |
ldap.connect.pool.initSize | 1 | The string representation of an integer that represents the number of connections per connection identity to create when initially creating a connection for the identity. |
ldap.connect.pool.maxSize | The string representation of an integer that represents the maximum number of connections per connection identity that can be maintained concurrently | |
ldap.connect.pool.prefSize | The string representation of an integer that represents the preferred number of connections per connection identity that should be maintained concurrently. | |
ldap.connect.pool.timeout | The string representation of an integer that represents the number of milliseconds that an idle connection may remain in the pool without being closed and removed from the pool. |
Connection parameters for apache-commons pool :
key | default | desc |
---|---|---|
ldap.connect.pool.maxActive | 8 | The maximum number of active connections of each type (read-only|read-write) that can be allocated from this pool at the same time, or non-positive for no limit. |
ldap.connect.pool.maxTotal | -1 | The overall maximum number of active connections (for all types) that can be allocated from this pool at the same time, or non-positive for no limit. |
ldap.connect.pool.maxIdle | 8 | The maximum number of active connections of each type (read-only|read-write) that can remain idle in the pool, without extra ones being released, or non-positive for no limit. |
ldap.connect.pool.minIdle | 0 | The minimum number of active connections of each type (read-only|read-write) that can remain idle in the pool, without extra ones being created, or zero to create none. |
ldap.connect.pool.maxWait | -1 | The maximum number of milliseconds that the pool will wait (when there are no available connections) for a connection to be returned before throwing an exception, or non-positive to wait indefinitely. |
ldap.connect.pool.whenExhaustedAction | block | Specifies the behaviour when the pool is exhausted. The FAIL option will throw a NoSuchElementException when the pool is exhausted. The BLOCK option will wait until a new object is available. If maxWait is positive a NoSuchElementException is thrown if no new object is available after the maxWait time expires. The GROW option will create and return a new object (essentially making maxActive meaningless) |
ldap.connect.pool.testOnBorrow | false | The indication of whether objects will be validated before being borrowed from the pool. If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made. |
ldap.connect.pool.testOnReturn | false | The indication of whether objects will be validated before being returned to the pool. |
ldap.connect.pool.testWhileIdle | false | The indication of whether objects will be validated by the idle object evictor (if any). If an object fails to validate, it will be dropped from the pool. |
ldap.connect.pool.timeBetweenEvictionRunsMillis | -1 | The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, no idle object evictor thread will be run. |
ldap.connect.pool.numTestsPerEvictionRun | 3 | The number of objects to examine during each run of the idle object evictor thread (if any). |
ldap.connect.pool.minEvictableIdleTimeMillis | 1000 * 60 * 30 | The minimum amount of time an object may sit idle in the pool before it is eligible for eviction by the idle object evictor (if any). |
Other new props:
key | default | desc |
---|---|---|
search.attribute.inDn | false | If set to true, signal that the users and groups ids are contains in the dn. Useful to improve the performance when lookup the members |
dynamic.enabled | false | Set to true if you want to use the dynamic groups |
Supporting both DX 7.0 and 7.1+
If you are building a module that should work for both DX 7.0 and 7.1+ you could use Reflection API calls to perform method invocations such as these :
protected JCRUserNode getUserNode(JCRSessionWrapper jcrSessionWrapper, String userName) {
// because of an API change between DF 7.0 and 7.1 we use reflection API to make sure we call the proper
// method.
try {
Method lookupUserMethod = jahiaUserManagerService.getClass().getMethod("lookupUser", String.class);
if (lookupUserMethod.getReturnType().equals(JahiaUser.class)) {
// DF 7.0 case
JahiaUser jahiaUser = (JahiaUser) lookupUserMethod.invoke(jahiaUserManagerService, userName);
if (jahiaUser != null && jahiaUser instanceof JCRUser) {
return (JCRUserNode) ((JCRUser) jahiaUser).getNode(jcrSessionWrapper);
}
} if (lookupUserMethod.getReturnType().equals(JCRUserNode.class)) {
JCRUserNode jcrUserNode = (JCRUserNode) lookupUserMethod.invoke(jahiaUserManagerService, userName);
return jcrUserNode;
} else {
logger.error("Unrecognized lookup user method " + lookupUserMethod.toString() + "!");
}
} catch (NoSuchMethodException e) {
logger.error("Error finding lookupUser method !", e);
} catch (InvocationTargetException e) {
logger.error("Error invoking lookupUser method !", e);
} catch (IllegalAccessException e) {
logger.error("Error invoking lookupUser method !", e);
} catch (RepositoryException e) {
logger.error("Error retrieving user JCR node !", e);
}
return null;
}
Be careful though because the Reflection API has a performance costs so if you intend to make a lot of these types of calls you should probably improve the above code by removing dynamic lookups as much as possible (try using static variables to store the method lookups)
As the above method returns a JCRUserNode decorator, some methods are not directly available in DX 7.0 so you might need to put them in your own code, such as the isAccountLocked method :
public boolean isAccountLocked(JCRUserNode jcrUserNode) {
try {
return !jcrUserNode.isRoot() && jcrUserNode.hasProperty("j:accountLocked") && jcrUserNode.getProperty("j:accountLocked").getBoolean();
} catch (RepositoryException e) {
logger.error(e.getMessage(), e);
return false;
}
}
Here is another example for accessing the getUserMembership() method that has also changed from DX 7.0 to 7.1 :
protected List<String> getUserMembership(JahiaUser jahiaUser) {
// because of an API change between DF 7.0 and 7.1 we use reflection API to make sure we call the proper
// method.
try {
Method getUserMembershipMethod = jahiaGroupManagerService.getClass().getMethod("getUserMembership", JahiaUser.class);
// we are in the DF 7.0 case
return (List<String>) getUserMembershipMethod.invoke(jahiaGroupManagerService, jahiaUser);
} catch (NoSuchMethodException e) {
// we are in the DF 7.1 case
try {
Method getUserMembershipMethod = jahiaGroupManagerService.getClass().getMethod("getUserMembership", String.class, String.class);
Method jahiaPrincipalMethod = jahiaUser.getClass().getMethod("getRealm");
String realm = (String) jahiaPrincipalMethod.invoke(jahiaUser);
return (List<String>) getUserMembershipMethod.invoke(jahiaGroupManagerService, jahiaUser.getUsername(), realm);
} catch (NoSuchMethodException e1) {
logger.error("Coudln't find any recognized getUserMembership method !", e1);
} catch (InvocationTargetException e1) {
logger.error("Error invoking getUserMembership method !", e1);
} catch (IllegalAccessException e1) {
logger.error("Error invoking getUserMembership method !", e1);
}
} catch (InvocationTargetException e) {
logger.error("Error invoking getUserMembership method !", e);
} catch (IllegalAccessException e) {
logger.error("Error invoking getUserMembership method !", e);
}
return null;
}