0% found this document useful (0 votes)
33 views

Limiting Data by User

This document discusses limiting data visibility and access for different user roles in a Liferay portal. It describes creating a read-only module that filters invoices to only show those associated with the current user's customer record. It also covers pre-filling customer data when a new order is created, while preventing editing of that information, to allow order creation while limiting details editing to just the logged in user's customer record. Configuration steps are provided to deploy the changes and security settings.

Uploaded by

Guillermo Aletti
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Limiting Data by User

This document discusses limiting data visibility and access for different user roles in a Liferay portal. It describes creating a read-only module that filters invoices to only show those associated with the current user's customer record. It also covers pre-filling customer data when a new order is created, while preventing editing of that information, to allow order creation while limiting details editing to just the logged in user's customer record. Configuration steps are provided to deploy the changes and security settings.

Uploaded by

Guillermo Aletti
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

261 Chapter 13: Security & navigation with Liferay

add new ones. Therefore, assigning the Invoices page to this role is not a valid
solution, because the portlet there allows the user to modify and add invoices. We
must add a new module to consult invoices. Edit the application.xml file of your
project adding the module of listing 13.2.
Listing 13.2 Read only module for Invoice defined in application.xml
<module name="ConsultInvoice">
<env-var name="XAVA_SEARCH_ACTION"
value="CRUD.searchReadOnly"/> <!-- Using this search action the data
is not editable in detail view -->
<model name="Invoice"/>
<controller name="Print"/><!-- Only print actions are available, CRUD is not included -->
</module>

In this simple way we define a read-only module for Invoice. Now, redeploy
your application and configure the security for this new module. During the
course of this chapter you have learned how to do it. You have to:
• Generate portlets and redeploy the application in Liferay (section 13.3).
• Add a new page named “Consult invoices” copying it from “Invoice”
page and put the ConsultInvoice portlet on the new page (section 13.4.4).
• Configure the page permissions making the page accessible by users with
the Seller role only (13.6.2).
Here you see how to give each user type (role) different privileges. Just create
modules with distinct capacities (distinct controllers) and assign them to the
desired roles inside Liferay.

13.6.4 Limiting list data visibility


Sometimes we want to limit not only the available functionality but also the
data the user can see. For example, we can allow the customers to login, and see
the list of their own orders, but obviously not the orders of other customers.
We can achieve this by filtering the complete list using a condition which
selects only orders which are associated with a given user id. Just add a new @Tab
annotation to the Order entity, as shown in listing 13.3.
Listing 13.3 New @Tab in Order to filter by customer
import org.openxava.filters.*; // For using UserFilter

...

@Tabs({

...
Access levels 262

@Tab(name="CurrentCustomer", // We use this name when defining the module


baseCondition =
"cast (${customer.number} as varchar) = ?", // Filtering by customer
filter=UserFilter.class, // Sets the current user as value for the parameter (the ?)
properties="year, number, date, customer.number, customer.name," +
"delivered, baseAmount, vat, totalAmount"
),
})
public class Order extends CommercialDocument {

As you already know baseCondition establishes a condition to be applied to


the list data. The question mark is the symbol for a parameter. The value of the
parameter is set by the UserFilter with the current user. UserFilter is included
in OpenXava. Note that we use a cast (cast ( as varchar)) in the condition.
This is because the customer.number is numeric and UserFilter returns a
string. Using a cast on a field in a condition is not very performant in some
databases (since it prevents the use of indexes). If you face this performance
issue, remove the cast from the condition and create your own filter
implementing the org.openxava.filters.IFilter interface to return the user
as a numeric value.
The next step is to define a module that uses this @Tab. The module definition
is given in listing 13.4; modify your application.xml accordingly.
Listing 13.4 Module to show the orders of the current customer
<module name="CustomerOrders">
<env-var name="XAVA_SEARCH_ACTION" value="CRUD.searchReadOnly"/>
<model name="Order"/>
<tab name="CurrentCustomer"/><!--This module uses CurrentCustomer tab for list data-->
<controller name="Print"/>
</module>

As you can see this module is a read only module that uses the
CurrentCustomer tab to list data. Now redeploy the application, add the menu
entry for this new module and configure its security:
• Generate portlets and redeploy the application in Liferay (section 13.3).
• Add a new page named “My orders” copying it from “Orders” page and
put the CustomerOrders portlet there (section 13.4.4).
• Configure the page permissions to be accessible only by users from
Customer role (13.6.2).
Note that the procedure relies on the fact that the customer number matches
the user id; users have to be created in the portal first, and then the customer has
to be created in the application. The portal's user id must be used as customer
number. The details are shown in figure 13.31.
263 Chapter 13: Security & navigation with Liferay

Control Panel

Invoicing application

1. Take note of the 2. Create a new customer


User ID of a user with using this User ID as
Customer role customer number

Figure 13.31 The customer number must match the user id


Here you see a portal user named “lulu”, whose user id is 12021. Then a
customer for “lulu” using the value 12021 for the number attribute is created. To
check that all is working you can create some orders for “lulu” using the Order
portlet. Afterwards, log into Liferay as “lulu” and you will see only the “My
orders” option on the Invoicing menu, and inside it a list for the orders of “lulu”.
Obviously this technique does not work if you have already created the
customers. In this case, add a new property to Customer, portalUser, and adapt
the base condition of the @Tab to filter for this property.

13.6.5 Limiting detail data visibility


An interesting way to improve My orders page for customers is to allow them
to create new orders from there. In this case, we only want to add the possibility
of creating new orders, but not to edit or remove the existing ones. Moreover, the
customer data must be prefilled from current user data and cannot be changed.
Figure 13.32 shows the desired behavior.
Access levels 264

Only My orders option is available

Lulu is from Customer role

Only New and Save

When clicking on New


the customer data is prefilled
and not editable

Figure 13.32 Creating a new order by a user of Customer role


To add this behavior to CustomerOrders module you have to define a new
controller. Modify its module definition in application.xml, as in listing 13.5.
Listing 13.5 CustomerOrders module with CustomerOrder controller
<module name="CustomerOrders">
<env-var name="XAVA_SEARCH_ACTION" value="CRUD.searchReadOnly"/>
<model name="Order"/>
<tab name="CurrentCustomer"/>
<controller name="CustomerOrders"/> <!-- Add this new controller -->
<controller name="Print"/>
</module>

This new controller, CustomerOrders, defines the “new” and “save” actions.
Listing 13.6 shows its definition in controllers.xml.
Listing 13.6 CustomerOrders controllers in controllers.xml
<controller name="CustomerOrders">

<!-- Defined like the standard CRUD.new but using a custom action -->
<action name="new"
class="org.openxava.invoicing.actions.NewOrderForCurrentUserAction"
image="images/new.gif"
keystroke="Control N"/>

<!-- Defined just like the standard CRUD.save -->


<action name="save" mode="detail"
class="org.openxava.actions.SaveAction"
image="images/save.gif"
keystroke="Control S"/>
265 Chapter 13: Security & navigation with Liferay

</controller>

This controller is a refined version of the standard CRUD controller of


OpenXava. We include only two actions, “new” and “save”. The save action is
just like the standard of OpenXava, but for the new action we use our own class.
Listing 13.7 shows the code of this class.
Listing 13.7 Action code for creating a new order from current user
package org.openxava.invoicing.actions; // In 'actions' package

import org.openxava.actions.*;
import org.openxava.util.*; // This package contains the Users class
import org.openxava.view.*;

public class NewOrderForCurrentUserAction extends NewAction {

public void execute() throws Exception {


super.execute(); // Executes the standard logic for new action
String user = Users.getCurrent(); // The id of the current logged user (1)
if (user == null) { // If there is no user logged
getView().setEditable(false);
addError("no_user_logged");
return;
}
int customerNumber = Integer.parseInt(user); // Because in Liferay the user id
// is a number, that we match with customer number
View customerView = getView().getSubview("customer");
customerView.setValue("number", customerNumber); // Fills the customer
// number in the view
customerView.findObject(); // This loads the customer data using the number as key
customerView.setKeyEditable(false); // The user cannot change the customer (2)
}

This action fills the customer data using the user id as a key. When the user
clicks the new button, the customer data will be filled automatically. An
important detail is that the customer view is not editable (2), this way the
searching list for customers is not available and the user cannot access to data of
other customers.
Note how to use Users.getCurrent() (a utility from org.openxava.util
package) to get the currently logged in user. This is a useful tool for limiting the
data visibility programmatically.

13.7 JUnit tests


Most of the work we have done in this chapter is about configuring our
application inside Liferay. We also have added some new modules to the
application: ConsultInvoice and CustomerOrders. The former is a mere

You might also like