oo

Adding the UAD Framework

You can manage and delete user data with Liferay’s User Associated Data (UAD) management tool. The tool is available out-of-the-box for many of Liferay’s applications (e.g. Blogs, Documents and Media, Message Boards, etc.). This framework can also be applied to your custom application.

This task is made easier with the use of Service Builder. See the example below to learn how Service Builder automatically generates the necessary code to enable UAD for your application.

Download the Example Code

Start a new Liferay DXP instance by running

docker run -it -m 8g -p 8080:8080 liferay/dxp:2024.q1.1

Sign in to Liferay at http://localhost:8080 using the email address test@liferay.com and the password test. When prompted, change the password to learn.

Then, follow these steps:

  1. Download and unzip UAD Framework.

    curl https://resources.learn.liferay.com/dxp/latest/en/users-and-permissions/developer-guide/liferay-h6d2.zip -O
    
    unzip liferay-h6d2.zip
    
  2. From the module root, build and deploy.

    ./gradlew deploy -Ddeploy.docker.container.id=$(docker ps -lq)
    
    note

    This command is the same as copying the deployed jars to /opt/liferay/osgi/modules on the Docker container.

  3. Confirm the deployment in the Liferay Docker container console.

    STARTED com.acme.h6d2.api_1.0.0 [1433]
    STARTED com.acme.h6d2.service_1.0.0 [1434]
    STARTED com.acme.h6d2.uad_1.0.0 [1435]
    STARTED com.acme.h6d2.web_1.0.0 [1436]
    
  4. Open your browser to https://localhost:8080.

  5. Add the H6D2 Portlet to a page. You can find the example portlet under Sample Widgets.

    Add the H6D2 Portlet to a page.

  6. Create a new user for testing.

  7. Log in as the new user and add some content on the H6D2 Portlet.

  8. Log back in as the administrator and navigate to Control PanelUsersUsers and Organizations.

  9. Click the new user’s Actions icon (Action) → Delete Personal Data. Click OK to confirm deactivation of the user.

  10. The UAD management tool appears. You can view, anonymize, or delete the data the new user added in the H6D2 Portlet.

    View, anonymize or delete the user's data that was added to the H6D2 Portlet.

Modify the Service Model Definition

This tutorial assumes that you have a working application that you created using Service Builder. To enable UAD, first make the following changes to your entity:

  1. Open your service.xml file in the -service folder.

  2. There are two entity parameters to enable UAD:

    entity attributes Description
    uad-application-name Specifies the name of the application the entity type belongs to.
    uad-package-path Specifies the package path for the generated UAD classes.
	<entity local-service="true" name="H6D2Entry" remote-service="false" uad-application-name="H6D2" uad-package-path="com.acme.h6d2" uuid="true">
  1. Add the following data fields if you don’t already have them defined:

    <!-- Group instance -->
    
    <column name="groupId" type="long" />
    
    <!-- Audit fields -->
    
    <column name="companyId" type="long" />
    <column name="userId" type="long" />
    <column name="userName" type="String" />
    <column name="createDate" type="Date" />
    <column name="modifiedDate" type="Date" />
    

    The UAD Framework requires these fields to track and anonymize user data.

  2. Next, specify the data fields to anonymize. This is done with the use of two attributes:

    • The uad-anonymize-field-name=[fieldName] attribute indicates a field whose value is replaced by that of the anonymous user in the UAD auto-anonymization process. For example, setting uad-anonymize-field-name=fullName would replace the value of that field with the full name of the anonymous user. See Configuring the Anonymous User to learn more about the anonymous user.

    • The uad-nonanonymizable="true" attribute indicates data that is not automatically anonymized but must be reviewed by an administrator.

<column name="userName" type="String" uad-anonymize-field-name="fullName" />

Generate the UAD module

  1. Navigate out of the -service folder and create a new -uad folder.

  2. Create a bnd.bnd file for the module.

Bundle-Name: Liferay H6D2 UAD
Bundle-SymbolicName: com.acme.h6d2.uad
Bundle-Version: 1.0.0
-dsannotations-options: inherit

Make sure to include the -dsannotations-options: inherit annotation. OSGi service component classes inherit OSGi declarative services annotations from their class hierarchy.

  1. Create a build.gradle file for the module.
dependencies {
	compileOnly group: "com.liferay.portal", name: "release.portal.api"
	compileOnly project(":h6d2-api")
}

Make sure to add any dependencies you need, including any -api module of your project.

  1. Navigate back to the module’s -service folder and run Service Builder to generate the UAD module.

    ../gradlew buildService
    

    Output:

    > Task :h6d2-service:buildService
    Building H6D2Entry
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/anonymizer/BaseH6D2EntryUADAnonymizer.java
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/exporter/BaseH6D2EntryUADExporter.java
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/anonymizer/H6D2EntryUADAnonymizer.java
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/exporter/H6D2EntryUADExporter.java
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/display/BaseH6D2EntryUADDisplay.java
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/display/H6D2EntryUADDisplay.java
    Writing src/main/resources/service.properties
    Writing ../h6d2-uad/src/main/java/com/acme/h6d2/uad/constants/H6D2UADConstants.java
    

Modify the Portlet

When you pass the data fields specific to your application from the form, you must also pass the user-related data fields you added in the service.xml file.

public class H6D2Portlet extends MVCPortlet {

	public void addH6D2Entry(
			ActionRequest actionRequest, ActionResponse actionResponse)
		throws PortalException {

		ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute(
			WebKeys.THEME_DISPLAY);

		User user = _portal.getUser(actionRequest);

		H6D2Entry h6d2Entry = _h6d2EntryLocalService.createH6D2Entry(
			_counterLocalService.increment());

		h6d2Entry.setCompanyId(user.getCompanyId());
		h6d2Entry.setUserId(user.getUserId());
		h6d2Entry.setUserName(user.getFullName());

		h6d2Entry.setGroupId(themeDisplay.getSiteGroupId());

		h6d2Entry.setName(ParamUtil.getString(actionRequest, "name"));

		_h6d2EntryLocalService.addH6D2Entry(h6d2Entry);
	}

	@Reference
	private CounterLocalService _counterLocalService;

	@Reference
	private H6D2EntryLocalService _h6d2EntryLocalService;

	@Reference
	private Portal _portal;

}

The H6D2 Portlet has an H6D2EntryLocalService field called _h6d2EntryLocalService and an action-handling method called addH6D2Entry. The addH6D2Entry method calls H6D2EntryLocalService’s addH6D2Entry method, passing the data fields received from the ActionRequest.

The portlet’s view.jsp contains a form users can submit in an ActionRequest to H6D2 Portlet.

<h5>Add H6D2 Entry</h5>

<portlet:actionURL name="addH6D2Entry" var="addH6D2EntryURL" />

<aui:form action="<%= addH6D2EntryURL %>">
	<aui:input name="name" type="text" />

	<aui:button type="submit" value="submit" />
</aui:form>

Submitting the ActionRequest with the actionURL invokes the portlet’s addH6D2Entry method.