atom feed9 messages in org.apache.incubator.isis-usersRE: per instance security
FromSent OnAttachments
Erik de HairApr 4, 2014 1:03 am 
Dan HaywoodApr 4, 2014 1:26 am 
Erik de HairApr 4, 2014 2:39 am 
Dan HaywoodApr 4, 2014 2:52 am 
Erik de HairApr 4, 2014 5:16 am 
Dan HaywoodApr 4, 2014 5:42 am 
Erik de HairApr 4, 2014 11:21 am 
Dan HaywoodApr 5, 2014 1:08 am 
Erik de HairApr 15, 2014 4:36 am 
Subject:RE: per instance security
From:Erik de Hair (er@pocos.nl)
Date:Apr 4, 2014 11:21:44 am
List:org.apache.incubator.isis-users

That works quit well. Thanks a lot!

It's also a good example to start exploring the crypts of Isis :-)

Erik

________________________________________ From: Dan Haywood [da@haywood-associates.co.uk] Sent: Friday, April 04, 2014 2:42 PM To: users Subject: Re: per instance security

On 4 April 2014 13:16, Erik de Hair <er@pocos.nl> wrote:

Hi Dan,

The sequence of actions executed by Isis during application execution is unclear to me. Furthermore All examples look method/member based to me and I have no clue how to hook into this sequence for hiding instances (or deny access).

You can get the current instance (which is called ObjectAdapter - a wrapper around the pojo domain object) from the supplied *Context.

All together it'd be something like...

public interface SecuredPerInstance { ... }

public class PerInstanceDisabilityFacetFactory extends FacetFactoryAbstract {

...

@Override public void process(final ProcessMethodContext processMethodContext) { final FacetedMethod member = processMethodContext.getFacetHolder(); final Class<?> owningClass = processMethodContext.getCls();

if(SecuredPerInstance.class.isAssignableFrom(owningClass)) { FacetUtil.addFacet(new PerInstanceDisabilityFacet(member)); } }

}

public class PerInstanceDisabilityFacet extends FacetAbstract implements DisablingInteractionAdvisor {

@Override public String disables(final UsabilityContext<? extends UsabilityEvent> ic) { if (!(ic instanceof UsabilityContext)) { return null; } final ObjectAdapter target = ic.getTarget(); final SecuredPerInstance pojo = (SecuredPerInstance)target.getObject();

// hacky... final String currentUser = IsisContext.getPersistenceSession().getServicesInjector().getContainer().getUser();

return poco.usableBy(currentUser) ? null: "Sorry, you can't modify this instance."; }

I think this is a bit too complex right now. I'm new to Isis and normally I would start doing more easy stuff to learn using Isis. But if we don't have 'per instance security' we can't use Isis. Is there any documentation about the principles of using these facet(factorie)s?

Nothing other than the doc I've already referenced, and the source code itself :-)

But perhaps the above will help; it should be possible to implement in about 30 lines of code or so...

Dan

Thanks, Erik

________________________________________ From: Dan Haywood [da@haywood-associates.co.uk] Sent: Friday, April 04, 2014 11:52 AM To: users Subject: Re: per instance security

On 4 April 2014 10:39, Erik de Hair <er@pocos.nl> wrote:

Hi Dan,

Your last option seems the most feasible option to me.

I presume I write my own permission-implementation then (for every domain class if necessary) to be used by "public List<String> visibleTo();"?

Would really like you to guide me. Where to start?

Ultimately, all you need is an implementation of FacetFactory to be registered in ProgrammingModel, where the FacetFactory installs a Facet on the metamodel members that implements HidingInteractionAdvisor or DisablingInteractionAdvisor.

To do the registration, see [1].

In terms of the FacetFactory, you could base it on something like HiddenFacetViaHideMethodFacetFactory, which is called for all members. You'll need to get the class of the member (from ProcessMethodContext argument) to determine whether the class itself implements the interface (if not, ignore).

In terms of the Facet, it merely must implement the *InteractionAdvisor interfaces. The existing HiddenFacet* and DisablingFacet* do this, but they are quite complex; a better option might be to use AuthorizationFacetAbstract for inspiration.

Let me know how you get on.

Dan

[1]

http://isis.apache.org/more-advanced-topics/metamodel-finetuning-the-programming-model.html

________________________________________ From: Dan Haywood [da@haywood-associates.co.uk] Sent: Friday, April 04, 2014 10:26 AM To: users Subject: Re: per instance security

On 4 April 2014 09:03, Erik de Hair <er@pocos.nl> wrote:

Hi,

I need per instance security in my application. What I want to do is extend AuthorisationRealm with doGetAuthorisationInfo() and implement my own permissions-scheme to check for the users permissions for a certain domain model instance.

I'm not sure that's the way to solve this.

With Shiro, the permission strings correspond to class members (possibly wildcarded to all members in a class, or to all classes in a package etc). So it is a class-based security mechanism, not an instance-based one.

That said, the way in which Shiro parses the permission string is pluggable, so in theory one could have a different permission scheme that includes the OIDs of objects (Company/L_10). But I don't think it'd be a very maintainable approach (lots of fiddly data to setup).

So I feel a better way to address this is up a level, within Isis....

Do I have to check for these permissions myself

You could, if you wanted, put the code in the domain objects, eg in the hide or disable methods, and get hold of the current user from getContainer(). But that would litter your domain code with lots of security stuff, which sounds unappealing.

Or... what I would probably explore is if there is some sort of convention whereby you could write a custom facet (implementing HidingInteractionAdvisor or DisablingInteractionAdvisor) such that you could do the per-instance security as a cross-cutting concern.

For example, each object that requires per-instance security could implement an interface:

public interface SecuredPerInstance {

// return the user or roles that this instance is visible for @Programmatic public List<String> visibleTo();

// return the user or roles that this instance can be used by (modifiable, invoke actions) @Programmatic public List<String> usableBy(); }

Then classes that need security would implement this instance, and the facet would advise based on the facet.

If that makes sense, I can guide you in writing such a facet if need be.

HTH Dan

and throw a security exception in case of no permission or is this

automatically done by Shiro when a client calls the restful interface like:

http://localhost:8080/restful/objects/nl.pocos.dom.Company/L_10