1 Reply Latest reply on Oct 28, 2008 9:21 AM by Marco Röösli

    Question about @Read annotation using with entityListener

    Marco Röösli Newbie

      I want to protect my DummyUser entity for the action update using the permissionStore and the PersistentPermissionResolver.


      I did this:


        @Transactional
         public DummyUser updateDummyUser(DummyUser dummyUser) {
           
            PersistentPermissionResolver pr = (PersistentPermissionResolver) Component.getInstance(
            PersistentPermissionResolver.class, false);
                
            if (pr.hasPermission(dummyUser, "update")==false)
            {
               Identity identity = (Identity) Component.getInstance(
                    Identity.class, false);
              throw new AuthorizationException("access denied for principal "+identity.getPrincipal().getName()+" for action=update");
            }
           
           return entityManager.merge(dummyUser);
         }



      that worked fine.


      I also tryed this:


         public DummyUser updateDummyUser(@Update DummyUser dummyUser) {
           return entityManager.merge(dummyUser);
         }




      that worked fine too but that is not that what I want. I want protect any update action on this entity. I don't want to set the annotation on all methods what can update this entity.


      So I began to try this (using the entityListener):




      @Entity
      @Table(name = "DUMMY_USER")
      @Identifier(value = EntityIdentifierStrategy.class)
      @Name("dummyUser")
      public class DummyUser implements Serializable {
      
         private static final long serialVersionUID = -3134097431661355175L;
      
         @Id
         @Column(name = "ID")
         @GeneratedValue(generator = "pomopSequenceGenerator")
         @GenericGenerator(name = "pomopSequenceGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
              @Parameter(name = "sequence_name", value = "POMOP_SEQUENCE"),
              @Parameter(name = "initial_value", value = "1000"), @Parameter(name = "increment_size", value = "1") })
         public Long id;
      
         @Column(name = "FIRSTNAME", length = 63, nullable = false)
         private String firstname;
      
         @Length(max = 20)
         @Column(name = "LASTNAME", length = 63, nullable = false)
         private String lastname;
      
         @Column(name = "EMAIL", length = 255, nullable = true)
         private String email;
      
         @OneToMany(cascade = CascadeType.ALL)
         private List<DummySettings> settings;
      
         @OneToOne(cascade = CascadeType.ALL)
         private DummySettings setting = new DummySettings("test");
      
         @PostLoad
         public void postLoad() {
         }
      
         @PreUpdate
         public void preUpdate() {
           
           
            PersistentPermissionResolver pr = (PersistentPermissionResolver) Component.getInstance(
                 PersistentPermissionResolver.class, false);
                     
                 if (pr.hasPermission(this, "update")==false)
                 {
                    Identity identity = (Identity) Component.getInstance(
                         Identity.class, false);
                   throw new AuthorizationException("access denied for principal "+identity.getPrincipal().getName()+" for action=update");
                 }
          }
      
      ....




      that was not working I'had got a loop because somewhere inside the hasPermission(..) method something happend that raised the PreUpdate event again.


      then I began to try this


      @PreUpdate
      @Update(DummyUser.class)
         public void preUpdate() {
           
          }
      



      that had no effect everybody was able to update my entity.



      then i tryed this.


      ....
      @PreUpdate
      @Restrict("#{persistentPermissionResolver.hasPermission(dummyUser,'update')}"
         public void preUpdate() {
           
          }
      ....
      


      there was the problem that the target object was not the right object it was a dummyUser object but with id null and the values was null also.


      I also tryed this


      ....
      @PreUpdate
      @Restrict("update")
         public void preUpdate() {
           
          }
      ....
      


      that gets me this exception in any cases even if the principle should be able to update the entity. It looks like its looking in my drools file but I dont want to add this rules there. how can I tell them to look in my permissionStore ?



      Caused by: org.jboss.seam.security.AuthorizationException: Authorization check failed for expression [update]




      Is it possible to protect the update acction on this enitty using the entityListener and the permissionStore for looking up the rules ?


      Thx for your help


      Greetz Marco


        • 1. Re: Question about @Read annotation using with entityListener
          Marco Röösli Newbie

          I found a solution now but I dont know if it's a good one:


          I did the protection for the read acton in my entity like this:


          @Entity
          @Table(name = "DUMMY_USER")
          @Identifier(value = EntityIdentifierStrategy.class)
          @Name("dummyUser")
          public class DummyUser implements Serializable {
          
             private static final long serialVersionUID = -3134097431661355175L;
             
             private static boolean updated=false;
          
             @Id
             @Column(name = "ID")
             @GeneratedValue(generator = "pomopSequenceGenerator")
             @GenericGenerator(name = "pomopSequenceGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
                  @Parameter(name = "sequence_name", value = "POMOP_SEQUENCE"),
                  @Parameter(name = "initial_value", value = "1000"), @Parameter(name = "increment_size", value = "1") })
             public Long id;
          
             @Column(name = "FIRSTNAME", length = 63, nullable = false)
             private String firstname;
          
             @Length(max = 20)
             @Column(name = "LASTNAME", length = 63, nullable = false)
             private String lastname;
          
             @Column(name = "EMAIL", length = 255, nullable = true)
             private String email;
          
             @OneToMany(cascade = CascadeType.ALL)
             private List<DummySettings> settings;
          
             @OneToOne(cascade = CascadeType.ALL)
             private DummySettings setting = new DummySettings("test");
          
             @PostLoad
             public void postLoad() {
             }
          
             @PreUpdate
             @Restrict
             public void preUpdate() {}
          
          



          then I made a rule in my droolsfile what calls my PermissionDelegator with the params target and action this params will be forwarded to my PersistentPermissionResolver.



          My rule to delegate the request to my store


          rule ManageDummyUserStorePermissions
           no-loop
           activation-group "permissions"
          when
            du: DummyUser()
            check: PermissionDelegator(target==du, action=="update")
          then
            check.grant();
          end



          my PermissionDelegator class


          @Name("permissionDelegator")
          public class PermissionDelegator {
          
            
             
             private Object target;
             private String action;
             
             @In
             Identity identity;
             
             public PermissionDelegator(Object target, String action)
             {
               this.target=target;
               this.action=action;
             }
             
             public void grant()
             {
                PersistentPermissionResolver pr = (PersistentPermissionResolver) Component.getInstance(
                       PersistentPermissionResolver.class, false);
          
                  if (pr.hasPermission(target, action) == false) {
                    throw new AuthorizationException("access denied for principal "+identity.getPrincipal().getName() +"for action=update");
                  }
             }
          
             public Object getTarget() {
                return target;
             }
          
             public void setTarget(Object target) {
                this.target = target;
             }
          
             public String getAction() {
                return action;
             }
          
             public void setAction(String action) {
                this.action = action;
             }
           
             
             
          }
          



          The dirty thing is that I need two entityManager one just for the security and the other one for my business logic. because if I use the same entityManager I get a loop. the perUpdate is called when someone change the entity but it will also called if I do an other query with the entityManager at this time.


          this solution works properly but is it a good solution? thx for your feedback


          greetz Marco