User API

Last modified by Admin on 2024/10/28 16:53

cogAPIs to manipulate users and groups
TypeJAR
CategoryAPI
Developed by

XWiki Development Team

Rating
0 Votes
LicenseGNU Lesser General Public License 2.1
Bundled With

XWiki Standard

Compatibility

Since 10.8RC1

Installable with the Extension Manager

Description

Users

Since 12.2 Concepts:

  • This API is independent from where the users are stored (in wiki pages, etc). This allows plugging other implementations to store the users elsewhere than in wiki pages (the default).
  • This API supports properties for the Guest and SuperAdmin users (i.e. even though these users do not have wiki pages for them, they still have properties, which are pre-defined, but can be configured, see below).
  • A user is pointed to with a UserReference. There are 3 special user references:
    • SuperAdminUserReference#INSTANCE: points to the SuperAdmin user
    • GuestUserReference#INSTANCE: points to the Guest user (i.e. not logged-in user)
    • CurrentUserReference#INSTANCE: special reference pointing to the current user
  • The UserProperties class represents the properties of a user (Editor to use, Advanced or Simple user, First name, etc), offering both a typed and untyped APIs.
    • Example of typed API: UserProperties#showHiddenDocuments()
    • Example of untyped API: UserProperties#getProperty('showHiddenDocuments')
  • Since 12.4RC1It's also possible to modify user properties by using setters in UserProperties and then calling save(). For example from Velocity (note that this will work even though setEmail accepts an InternetAddress because we have an InternetAddress Converter):
    #set ($props = $services.user.getProperties('user'))
    Current email: $props.email
    #set ($discard = $props.setEmail('john@doe.com'))
    #set ($discard = $props.save())
  • To get a UserProperties object, you use a UserPropertiesResolver. For example from a Java component:
    @Inject
    private UserPropertiesResolver userPropertiesResolver;
    ...
    UserProperties currentUserProperties = userPropertiesResolver.resolve(CurrentUserReference.INSTANCE);
    • There are different UserPropertiesResolver, depending on whether you need to get properties explicitly defined for the user or whether you also want to check fallback properties (for example user properties defined for the current space - <space>.WebPreferences -, for the current wiki - XWiki.XWikiPreferences -, and ultimately in the xwiki.properties configuration file). Examples:
      // Resolver to get explicitly-defined properties without fallbacks:
      @Inject
      private UserPropertiesResolver userPropertiesResolver;

      // Resolver to get properties with full fallbacks:
      @Inject
      @Named("all")
      private UserPropertiesResolver userPropertiesResolver;
  • To test if a UserReference is pointing to the SuperAdmin user, you'll write:
    ...
    UserReference userReference = ...
    if (SuperAdminUserReference.INSTANCE == userReference) {
       ...
    }
  • To test if a UserReference is pointing to the Guest user, you'll write:
    ...
    UserReference userReference = ...
    if (GuestUserReference.INSTANCE == userReference) {
       ...
    }
  • To test if the current user is pointing to the Guest user, you'll first need to resolve the user, as in:
    @Inject
    private UserReferenceResolver<CurrentUserReference> resolver;
    ...
    UserReference userReference = this.resolver.resolve(CurrentUserReference.INSTANCE);
    if (GuestUserReference.INSTANCE == userReference) {
       ...
    }

    This is currently needed because XWikiContext#getUserReference() doesn't return a UserReference (it returns a DocumentReference). When this is fixed in the future, it'll be as simple as writing:

    UserReference userReference = xwikiContext.apiToGetTheUserReference()
    if (GuestUserReference.INSTANCE == userReference) {
       ...
    }
  • UserManager: Component to perform CUD operations (the R from CRUD is done with the UserPropertiesResolver). Right now, only offers an exist() method, as in:
    @Inject
    private UserManager userManager;
    ...
    userManager.exists(CurrentUserReference.INSTANCE);

Full API in the javadoc.

Configuration

The UserConfiguration component provides a way to access the User module's configuration from Java.

User properties can be configured in several places. The following order is used to find them:

  1. In the current user profile page (i.e. technically in the XWiki.XWikiUsers xobject in the current user profile page)
  2. If not found, in the current space preferences (i.e. technically in the XWiki.XWikiPreferences xobject of the current space) and if not found, in all the parent spaces preferences of the current space
  3. If not found, in the current wiki preferences (i.e. technically in the XWiki.XWikiPreferences xobject of the XWiki.XWikiPreferences page of the current wiki)
  4. If not found, in the xwiki.properties configuration file. It's currently not recommended to use this configuration level, since there's a known bug

It's also possible to configure the default preferences for the Super Admin and Guest users. This is done through the xwiki.properties configuration file:

#-# [Since 12.2]
#-# Define preferences for the SuperAdmin user.
#-#
#-# The format is:
#-# user.preferences.superadmin.<preference name> = <value>
#-#
#-# Values set by default for the SuperAdmin user:
#-# user.preferences.superadmin.displayHiddenDocuments = 1
#-# user.preferences.superadmin.active = 1
#-# user.preferences.superadmin.first_name = SuperAdmin
#-# user.preferences.superadmin.email_checked = 1
#-# user.preferences.superadmin.usertype = Advanced
#-#
#-# Examples:
#-# user.preferences.superadmin.displayHiddenDocuments = 0
#-# user.preferences.superadmin.editor = Text

#-# [Since 12.2]
#-# Define preferences for the Guest user.
#-#
#-# The format is:
#-# user.preferences.guest.<preference name> = <value>
#-#
#-# Values set by default for the Guest user:
#-# user.preferences.guest.displayHiddenDocuments = 0
#-# user.preferences.guest.active = 0
#-# user.preferences.guest.first_name = Guest
#-# user.preferences.guest.email_checked = 0
#-#
#-# Examples:
#-# user.preferences.guest.displayHiddenDocuments = 1
#-# user.preferences.guest.editor = Text

You can also configure an user property to be used as differentiator (hint) when displaying users in compact mode, in order to better identify users that have common or similar names. You can use an existing user property, like address, or a custom user property that you need to add first to the XWiki.XWikiUsers class (e.g. the position inside the organization).

#-# [Since 14.10.12]
#-# [Since 15.5RC1]
#-# When displaying an user in a compact mode we usually rely only on the user avatar and their full name. If this is
#-# not enough to properly identify the user then this configuration can be used to display additional information.
#-#
#-# The name of the user property to be used as qualifier (hint) when displaying the user in a compact mode. This
#-# configuration is not set by default, which means no additional information is displayed:
# user.display.qualifierProperty =

For instance:

user.display.qualifierProperty = address

At the moment this configuration is taken into account only by the user picker, and is not set by default, meaning that we don't show any differentiator by default.

History

There are various APIs in XWiki for retrieving user properties. A lot of them are historical and old and shouldn't be used. Here are all possibilities:

  1. Direct XWiki.XWikiUsers XObject access: This is totally not recommended and you shouldn't do that. Use this API instead.
  2. XWiki#getUserPreference(): Gets a user property and if it doesn't exist fallback to looking in the current space's WebPreferences and if it doesn't exist, fallback to looking in the current wiki's XWikiPreferences. It has been retrofitted to call this User API and is thus safe to use. However don't use it, and, instead, use this API which also implements fallbacks.
  3. com.xpn.xwiki.user.api.XWikiUser & XWikiContext#getXWikiUser(): Old API, based on users stored in wiki pages and part of oldcore. Shouldn't be used.
  4. user ConfigurationSource: Low-level and untyped API for getting user properties. It's recommended to not use it because 1) it's not typed and 2) it only supports users stored in wiki documents (except for SuperAdmin and Guest users).
  5. UserProperties: This new API described on this page: This is the recommended API to use!

Bridge

The following explanations can help you bridge from old APIs to the new API. They're not recommended to be used since they break the goal of the User API which is to hide the implementation details of where Users are stored. But it can be temporarily useful.

  • If you need to retrieve properties for an old XWikiUser, you can do it like this:
    @Inject
    private UserReferenceResolver<XWikiUser> xwikiUserUserReferenceResolver

    @Inject
    private UserPropertiesResolver userPropertiesResolver;
    ...
    XWikiUser oldXWikiUser = ...
    UserProperties properties = userPropertiesResolver.resolve(xwikiUserUserReferenceResolver.resolve(oldXWikiUser));
  • If you need to get a UserReference from a DocumentReference you'll need a UserReferenceResolver. For example:
    @Inject
    @Named("document")
    private UserReferenceResolver<DocumentReference> userReferenceResolver;
    ...
    DocumentReference documentReference = ...
    UserReference reference = userReferenceResolver.resolve(documentReference);
  • If you need to get a UserReference from a user represented as String, you can write:

    Example 1:

    @Inject
    private UserReferenceResolver<String> userReferenceResolver;
    ...
    UserReference reference = userReferenceResolver.resolve("XWiki.superadmin");

    Example 2: user reference without the space

    @Inject
    private UserReferenceResolver<String> userReferenceResolver;
    ...
    UserReference reference = userReferenceResolver.resolve("superadmin");

    Example 3: User in a specific wiki

    @Inject
    private UserReferenceResolver<String> userReferenceResolver;
    ...
    UserReference reference = userReferenceResolver.resolve("SomeUser", new WikiReference("somewiki"));
    // OR
    UserReference reference = userReferenceResolver.resolve("somewiki:XWiki.SomeUser");
  • If you need to get a DocumentReference from a UserReference you can write:
    @Inject
    @Named("document")
    private UserSerializer<DocumentReference> documentUserSerializer;
    ...
    UserReference userReference =  ...
    DocumentReference documentReference = documentUserSerializer.serialize(userReference);

Groups

The org.xwiki.user.group.GroupManager component allows getting information about the groups and their members.

Everything you request trough this component is cached for fast access.

Member's groups

/**
     * Search groups the passed user or group is member of.
     * <p>
     * {code wikis} controls where to search for the groups and {@code recurse} only the direct group should be
     * returned or the whole hierarchy.
     *
     * @param member the group member (user or group)
     * @param wikiTarget the wikis where to search. The following types are supported:
     *            <ul>
     *            <li>{@link org.xwiki.user.group.WikiTarget}</li>
     *            <li>{@link String}</li>
     *            <li>{@code Collection<String>}</li>
     *            <li>{@code org.xwiki.model.reference.WikiReference}</li>
     *            <li>{@code Collection<org.xwiki.model.reference.WikiReference>}</li>
     *            </ul>
     * @param recurse false if only the direct groups should be returned, true to take into account groups of groups
     * @return the groups the passed user or group is member of
     * @throws GroupException when failing to get groups
     */

    Collection<DocumentReference> getGroups(DocumentReference member, Object wikiTarget, boolean recurse)
       throws GroupException;

Group's members

    /**
     * Retrieve the users and groups which are the members of the passed group.
     *
     * @param group the group for which to return the members
     * @param recurse false if only the direct members should be returned, true to take into account groups of groups
     * @return the members of the passed group
     * @throws GroupException when failing to get members
     */

    Collection<DocumentReference> getMembers(DocumentReference group, boolean recurse) throws GroupException;

Prerequisites & Installation Instructions

We recommend using the Extension Manager to install this extension (Make sure that the text "Installable with the Extension Manager" is displayed at the top right location on this page to know if this extension can be installed with the Extension Manager).

You can also use the manual method which involves dropping the JAR file and all its dependencies into the WEB-INF/lib folder and restarting XWiki.

Dependencies

Dependencies for this extension (org.xwiki.platform:xwiki-platform-user-api 16.9.0):

Get Connected