Not so well known feature - ResourceBlock Permissions

Introduction

I decided to write this blog as I did find out that this is the area of the Liferay that has not been documented at all?  So this blog post can act as documentation for this. So let's talk about entity/model permissions and especially ResourceBlock permission.

If you are not familiar with Liferay’s permission system I would suggest that you go and first read our documentation or even better to participate our wonderful Developer 1 training before continuing your journey with this blog post.

As you are ready to learn!

As now you are continuing the reading, I can assume that you now are familiar how to implement permissions checking and how to filter results with filterFindBy<..>(..).

What we teach on our courses or our documentation is mainly how to implement entity/model permissions with ResourcePermissions, but we are not talking ResourceBlock permissions at all.

As you might know ResourcePermission table is place where the permissions are stored and primKey contains information of the entity's primary key. So basically every entity/model at Liferay will generate one or more rows to ResourcePermission table.

This also means that, ResourcePermission table size grows quickly. When you look this more carefully, you find out that same permission pattern is replicated over and over again. This means that, you can expect the ResourcePermission table to be huge with large Liferay DB. So if you have 1 000 000 entity rows your resourcePermission table might easily contain 6 000 000 rows.

What ResourceBlock is bringing to this?

ResourceBlock permissioning has brought improvement for this by minimizing data duplication by introducing ResourceBlock system.

When using ResourceBlockPermissions, then these similar permissions sets are recognized as blocks,and stored only once so less duplicated information is stored. This is done automatically for you and new block is created if the new combination of permissions has been found. Permission set is recognized by calculation unique permissionHash. There is also difference how the RecourceBlock is bound to the entity/model. With ResourceBlock permissions entity/model's primary key is not used for filtering rows or checking access, but special resourceBlockId, which is required to be added to the entity/model. This causes your entity to implement PermissionedModel interface and that is also how Liferay knows that you are using ResourceBlock permissions.

Let's go and see how to implement ResourceBlock permissions "step by step"

Make sure that your entity has resourceBlockId at your entity defintion at service.xml.

<!-- Permission fields -->

<column name="resourceBlockId" type="long" />

Create default.xml and register that to portlet.properties.

Run ServiceBuilder and you see that our entity is implementing PermissionedModel

public interface Foo extends FooModel, PermissionedModel {

}

Register your entity at your LocalService layer were you persist your entity.

foo = fooPersistence.update(foo);

serviceContext.setAddGuestPermissions(true);
serviceContext.setAddGroupPermissions(true);

resourceLocalService.addModelResources(foo, serviceContext);

also remember to remove resource if when you are deleting the entity/model.

resourceLocalService.deleteResource(foo, ResourceConstants.SCOPE_INDIVIDUAL);
return super.deleteFoo(foo);

Basically that's it smiley .. hopefully did remember all steps. 

See also example app below.

Where this is used?

Currently Bookmarks and Calendar are using ResourceBlocks.

Performance:

With MySQL/MariaDB adding entities with ResourceBlock permissioning is slower, but reading is hugely faster. With ResourceBlock and millions of data is unlikely that read will come a problem.

Examples:

Take a look the example application at github, which contains both example with ResourcePermission and ResourceBlockPermission implementation.

https://github.com/sammso/tester-liferay-permission

Issues:

While writing this, blog I did found out that ResourceBlock has little hickup and seems to leave orphan rows to ResourceBlockPermission table, but that does not effect performance. Issue: LPS-55244

Blogs
Are there any problems with the permissions scope? I have to define the permissions for all sites in a instance (instace scope). Is it possible? and if yes ,how ? thanks.
I have a question about (https://github.com/sammso/tester-liferay-permission) project , To run the project,I will find the table ResourceBlockPermission ,there are so many extra useless datas.