0

In a JHipster based project, we need to selectively filter out certain columns based on role/user logged in. All users will be able to view/modify most of the columns, but only some privileged users will be able to view/modify certain secure fields/columns.

It looks like the only option to get this done is using EntityListeners. I can use an EntityListener and mask a certain column during PostLoad event. Say for example, I mask the column my_secure_column with XXX and display to the user.

User then changes some other fields/columns (that he has access to) and submits the form. Do I have to again trap the partially filled in entity in PreUpdate event, get the original value for my_secure_column from database and set it before persisting?

All this seems inefficient. Scoured several hours but couldn't find a specific implementation that best suits this use case.

Edit 1: This looks like a first step to achieving this in a slightly better way. Updating Entities with Update Query in Spring Data JPA

I could use specific partial updates like updateAsUserRole, updateAsManagerRole, etc., instead of persisting the whole entity all the time.

@Repository
public interface CompanyRepository extends JpaRepository<Company, Integer> {
   @Modifying(clearAutomatically = true)
   @Query("UPDATE Company c SET c.address = :address WHERE c.id = :companyId")
   int updateAddress(@Param("companyId") int companyId, @Param("address") String address);
}
user1880957
  • 1,146
  • 3
  • 15
  • 29

1 Answers1

1

Column based security is not an easy problem to solve, and especially in combination with JPA.

Ideally you like to avoid even loading the columns, but since you are selecting entities this is not possible by default, so you have to remove the restricted content by overriding the value after load.

As an alternative you can create a view bean (POJO) and then use JPQL Constructor Expression. Personally I would use CriteriaBuilder. construct() instead of concatenating a JPQL query, but same principle.

With regards to updating the data, the UI should of cause not allow the editing of restricted fields. However you still have to validate on the backend, and I would recommend that you check if the column was modify before calling JPA. Typically you have the modifications in a DTO and would need to load the Entity anyway, if a restricted column was modified, you would send an error back. This way you only call JPA after the security has been checked.

Community
  • 1
  • 1
Klaus Groenbaek
  • 4,820
  • 2
  • 15
  • 30
  • In JHipster, typically on an update, data gets bound to the entity directly (there is no need for a separate DTO). So, in a normal case we don't load the Entity. It's just an update/save on the bound object received from browser. But for this specific use case, it looks like we will have to load the entity all over again, compare and merge. This seems to be a wasteful exercise. – user1880957 Jan 06 '17 at 16:09
  • I have looked at JHipster, and although it get you up and running I would never use it for production. As with any code generation, trying to build a general fit-all framework it will always fail (my 13 year opinion). We have Junior resource that wanted to use JHipster, and it gives you a good idea of which components are needed, but you should create a new project and trim away the fat - The default (monolitic) JHipster project is 5000+ lines, typically you need 10% of that, the rest needs to be customized in some way. Do yourself a favour and learn Spring (Core, Boot, Security, Data) – Klaus Groenbaek Jan 06 '17 at 18:14
  • I have never used the same class as Entity and DTO. I know that most JPA frameworks offer built in REST services to manipulate data, but in my experience this is a mistake. There are simply different requirements to an Entity and a DTO, and you often need a security layer before updating the database. Creating as DTO for you entities is a one time task of about 1-5 minutes, this is nothing compared to the time you will spend mangeling you entity class to make it do both. You can take my word on the matter, or learn it for yourself ;) – Klaus Groenbaek Jan 06 '17 at 18:27