Tuesday, July 26, 2016

Liferay Permission checker for guest user

Liferay has permission checker where user related permissions are available. Whenever we are giving access to specific resources then we will use permission checker. From permission checker we will use has permission to check the user permissions, permission checker object will be ready when the user login into the Liferay portal.

In JSP level we will use following code to get user permission checker Object.


PermissionChecker permissionCheckerObj = themeDisplay.getPermissionChecker();

Or We have JSP implicit variable for permission checker as follows.

permissionChecker

Finally we will use has permission method to check whether user have permission or not as follows.

permissionChecker.hasPermission(-----);



Another scenario where we are calling XXXServiceUtil methods of service layer, these are services which need to passing through permission checker and permission checker will check whether user has right permission to call these methods or not, otherwise it throws PrincipalException says that permission checker is not set.

Generally XXXServiceUtil methods are for login user or user should have right permission to use these calls otherwise it throws exception.

Example:


UserServiceUtil.addUser(----);
GroupServiceUtil.addGroup(----);

OR

themeDisplay.getScopeGroup().getExpandoBridge().addAttribute("test");


Above methods calls will fails when we are invoking as guest user, it means executing these methods without login into Liferay portal. If the user does not have right permission to call these methods then it will throw following exception stack trace.



com.liferay.portal.security.auth.PrincipalException
            at com.liferay.portal.service.permission.
PortletPermissionImpl.check(PortletPermissionImpl.java:161)
            at com.liferay.portal.service.permission.
PortletPermissionUtil.check(PortletPermissionUtil.java:113)
            at com.liferay.portlet.expando.service.
impl.ExpandoColumnServiceImpl.
addColumn(ExpandoColumnServiceImpl.java:47)

But we can call these methods as guest user and we will call these methods on behalf of Admin user permission checker object such way we can use these services.

The following is code to call XXXServiceUtil methods on behalf of administrator and this will work any time it means whether you login into portal or not.

The following is example


Role adminRole = RoleLocalServiceUtil.getRole(CompanyThreadLocal.getCompanyId(), "Administrator");
List<User> adminUsers = UserLocalServiceUtil.getRoleUsers(adminRole.getRoleId());
long userId = 20159;
if(adminUsers != null && !adminUsers.isEmpty()) {
            userId = adminUsers.get(0).getUserId();
}
User user1 = UserLocalServiceUtil.getUser(userId);
PermissionChecker checker = PermissionCheckerFactoryUtil.create(user);
PermissionThreadLocal.setPermissionChecker(checker);
UserServiceUtil.addUser(--);
GroupServiceUtil.addGroup(--);



 We need to get admin user and we can create permission checker object, finally we will set permission object to Permission Thread Local so that permission checker is available. Once you set permission checker next code lines we can call XXXServiceUtil methods then it will be successfully invoked.

Note:

This is not recommended way but some scenarios when it needed where we can use it.
Let’s say we are writing some application start up hooks where we may need use  XXXServiceUtil methods need to be called then it will be useful. Because we are not sure while deploy the hook portal is login with user or not, otherwise method invocation will get failed after deployment of hook.

Let’s say in our custom portlet service layer we may need portal XXXServiceUtil methods in that scenarios also we can use it.

All of methods are available in XXXLocalServiceUtil but some scenarios if not available then it may useful.
Author

Sunday, July 24, 2016

Liferay Upgrade Process

Liferay Upgrade process is way to perform pre configurations related to portlet or Liferay applications.

When we can use Upgrade Process?
  1. When we move our applications from one version to another version we may need to do some pre configuration to work well in newer environment.
  2. If application need to populate some default data with respect application.
  3. Database related SQL script execution.

Upgrade Process will be implemented through hooks in Liferay. We can create a separate hook plugin or we can create with in the portlet as hook.

Steps:
  1. Implement Upgrade Process Java Class.
  2. Configure Upgrade Process details in hook properties file.

Implement Upgrade Process Java Class

We need to implement one Upgrade process java class and that must be extends UpgradeProcess class. We will write all configuration logic in doUpgrade(--)


public class CustomUpgradeProcessProcess_1_1_0 extends UpgradeProcess {
public int getThreshold() {
return 110;
}
protected void doUpgrade() throws Exception {
_log.info("=====Upgrade Process Started=====");
setUpApplication();
runStatesSQL();

}

protected void setUpApplication() throws Exception {

_log.info("=====Upgrade Process Logic here=====");
}
protected void runStatesSQL() throws Exception {
_log.info("=====Upgrade Process Executing SQL Script=====");
runSQL("INSERT INTO Region VALUES (1085,108,'IN_AP','Andhra Pradesh',1) ,(1086,108,'IN_TN','TamilNadu',1),(1087,108,'IN_AR','Arunachal Pradesh',1)");

}
private static Log _log = LogFactoryUtil.getLog(CustomUpgradeProcessProcess_1_1_0.class);
}


Threshold is a number it will be stored in release_ table. When we deploy hook then it will check with the number that already stored in release_. If the number is higher than the value in release_ table then it will trigger the upgrade process.

runSQL(--) is a method to execute SQL script. We need to provide a valid SQL script.
doUpgrade(--) is a method will trigger when hook is deployed successfully.

Configure Upgrade Process Details in hook properties file

Now we need to configure Upgrade process information in hook properties file.


release.info.build.number=110
release.info.previous.build.number=100

upgrade.processes=\
    com.meera.upgrade.CustomUpgradeProcessProcess_1_1_0


If we have multiple process then separate with new line


upgrade.processes=\
    com. meera.upgrade.SetupOrganizationApplicationProcess_1_1_0,\
    com. meera.upgrade.SetupSiteApplicationProcess_1_1_0


Build number is stored in release_ after upgrade process completed successfully. Generally this will be current build number which is available in portlet service.properties file.

Once upgrade processes is completed then build number will be stored in Liferay relase_ table. When we deploy same hook for next time, it won’t start upgrade process again.
If you want to run upgrade process again then we will create another java class with higher number and need to change build number in hook properties file.

The following screen shows that build number stored in release_ table against upgrade processes hook.


Sample Application:

Assume we have a requirement where we wanted to create organization with some default pages.

We will use upgrade process hook, with that we will create Organization. Once organization is created, we will create some default pages for it.

Complete Code example

Upgrade Process Java Class (SetupOrganizationApplicationProcess_1_1_0)


package com.meera.upgrade.process;

import java.util.ArrayList;
import java.util.List;

import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.upgrade.UpgradeProcess;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.CountryConstants;
import com.liferay.portal.model.Layout;
import com.liferay.portal.model.LayoutConstants;
import com.liferay.portal.model.ListTypeConstants;
import com.liferay.portal.model.Organization;
import com.liferay.portal.model.OrganizationConstants;
import com.liferay.portal.model.RegionConstants;
import com.liferay.portal.model.Role;
import com.liferay.portal.model.User;
import com.liferay.portal.service.LayoutLocalServiceUtil;
import com.liferay.portal.service.OrganizationLocalServiceUtil;
import com.liferay.portal.service.RoleLocalServiceUtil;
import com.liferay.portal.service.ServiceContext;
import com.liferay.portal.service.UserLocalServiceUtil;
import com.liferay.portal.util.PortalUtil;

/**
* @author meeraprince
*
*/
public class SetupOrganizationApplicationProcess_1_1_0 extends UpgradeProcess {
public static String[] pageNames ={"Welcome","Products","Services","Contact Us"};
public static String ORG_NAME = "LiferaySavvy";
public int getThreshold() {
return 110;
}
protected void doUpgrade() throws Exception {
_log.info("==========SetupApplicationProcess_1_1_0===============");
setUpApplication();
}

protected void setUpApplication() throws Exception {
Organization organization = createOrganization();
if(Validator.isNotNull(organization)){
createPages(organization);
}
try{
runStatesSQL();
}catch(Exception e){
_log.error(e.getLocalizedMessage());
if(_log.isDebugEnabled()){
_log.debug(e.toString());
e.printStackTrace();
}
}


}
protected Organization createOrganization() throws Exception {
_log.info("createOrganization Process started");
Organization organization = null;
boolean site = true;
String name = ORG_NAME;
String type =  OrganizationConstants.TYPE_REGULAR_ORGANIZATION;
long regionId = RegionConstants.DEFAULT_REGION_ID;
long countryId = CountryConstants.DEFAULT_COUNTRY_ID;
long companyId = getCompanyId();
long userId = getAdminUserId();
ServiceContext serviceContext = new ServiceContext();
String friendlyURL = name;
friendlyURL = friendlyURL.replace(StringPool.SPACE,StringPool.DASH);
long parentOrganizationId = OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID;
try{
organization = OrganizationLocalServiceUtil.getOrganization(companyId, name);
}catch(Exception e){
_log.error(e.getLocalizedMessage());
if(_log.isDebugEnabled()){
_log.debug(e.toString());
e.printStackTrace();
}
}
try{
if(Validator.isNull(organization)){
organization = OrganizationLocalServiceUtil.addOrganization(userId, parentOrganizationId, name, type, regionId, countryId, ListTypeConstants.ORGANIZATION_STATUS_DEFAULT,name, site, serviceContext);
}else{
_log.info("Organization Name already existed in your Liferay Portal.");
}

}catch(Exception e){
_log.error(e.getLocalizedMessage());
if(_log.isDebugEnabled()){
_log.debug(e.toString());
e.printStackTrace();
}
}
return organization;
}
protected List<Layout> createPages(Organization organization) throws Exception {
_log.info("createPages Started");
List<Layout> pagesList = new ArrayList<Layout>();
for (String pageName : pageNames) {
Layout page = createPage(organization,pageName);
if(Validator.isNotNull(page)){
pagesList.add(page);
}
}
return pagesList;
}
protected Layout createPage(Organization organization,String name) throws Exception {
_log.info("createPage Started");
long userId = getAdminUserId();
long groupId = organization.getGroupId();
boolean privateLayout = false;
String title = name;
String description = name;
String type = LayoutConstants.TYPE_PORTLET;
boolean hidden = false;
String friendlyURL = name;
friendlyURL = friendlyURL.replace(StringPool.SPACE,StringPool.DASH);
friendlyURL = StringPool.FORWARD_SLASH + friendlyURL.toLowerCase();
_log.info("friendlyURL"+friendlyURL);
ServiceContext serviceContext = new ServiceContext();
long parentLayoutId = 0L;
Layout layout = null;
try{
layout = LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(groupId, privateLayout, friendlyURL);
}catch (Exception e) {
_log.error(e.getLocalizedMessage());
e.printStackTrace();
if(_log.isDebugEnabled()){
_log.debug(e.toString());
e.printStackTrace();
}
}
try {

if(Validator.isNull(layout)){
layout = LayoutLocalServiceUtil.addLayout(userId, groupId, privateLayout,parentLayoutId, name, title, description, type, hidden,
friendlyURL, serviceContext);
}
} catch (PortalException e){
_log.error(e.getLocalizedMessage());
e.printStackTrace();
if(_log.isDebugEnabled()){
_log.debug(e.toString());
e.printStackTrace();
}
}
return layout;
}
protected long getAdminUserId() throws Exception {
Role adminRole = RoleLocalServiceUtil.getRole(getCompanyId(), "Administrator");
List<User> adminUsers = UserLocalServiceUtil.getRoleUsers(adminRole.getRoleId());
long userId = 20159;
if(adminUsers != null && !adminUsers.isEmpty()) {
userId = adminUsers.get(0).getUserId();
}
return userId;
}
protected long getCompanyId() throws Exception {
return PortalUtil.getDefaultCompanyId();

}

protected void runStatesSQL() throws Exception {
runSQL("INSERT INTO Region VALUES (1085,108,'IN_AP','Andhra Pradesh',1) ,(1086,108,'IN_TN','TamilNadu',1)");
}
private static Log _log = LogFactoryUtil.getLog(SetupOrganizationApplicationProcess_1_1_0.class);
}


Hook properties configuration (portal.properties)


release.info.build.number=110
release.info.previous.build.number=100
upgrade.processes=\
    com.meera.upgrade.process.SetupOrganizationApplicationProcess_1_1_0


Download Upgrade Process Hook


After successful deployment of hook, organization will be created with default pages.
If we access the following URL then we can see newly created organization





Recent Posts

Recent Posts Widget

Popular Posts