OK, folks, I've just committed and pushed [1] to isis-module-security, to
support both factories and contributions (by emitting events for all
actions).

I'll add a wiki page soon, but it'll only have the same info as is in this
thread.

Cheers
Dan

[1] https://github.com/isisaddons/isis-module-security/issues/5


On 21 November 2014 10:02, Dan Haywood <[email protected]> wrote:

> Hi Martin,
>
> The point of this second design is that Organisation is your domain class,
> not part of the security module, so it can have whatever you want in it.
>
> Cheers,
> Dan
> On 21 Nov 2014 09:46, "Martin Balmaceda" <[email protected]>
> wrote:
>
>> Greetings
>>
>> Thanks Dan, a great suggestion and not as crazy complicated as I was
>> expecting.
>> One question though: how extensible would the Organization be in this
>> case?
>> I imagine every use case would require this class to represent something
>> different.
>>
>> On Thu, Nov 20, 2014 at 7:02 PM, Dan Haywood <
>> [email protected]>
>> wrote:
>>
>> > Hi folks,
>> >
>> > Great to see this thread with lots of useful contributions from
>> everyone.
>> >
>> > ~~~
>> > As Jeroen has said, we definitely intend to enhance the security module,
>> > though only as the exact requirements become clear.
>> >
>> > For Martin's requirement, to allow an Organization to be associated with
>> > the ApplicationUser, and also for Johan's that sounds similar, we
>> basically
>> > want to have somewhere to store the AppUser/Organization tuple.
>> >
>> > I can see two approaches.
>> >
>> > 1. store the AppUser/Org tuple in a subclass of ApplicationUser
>> >
>> > 2. store the AppUser/Org tuple as a separate entity (let's call it
>> > OrganizationUser) that is 1:1 with the AppUser, and then use contributed
>> > properties and actions to make it appear as if the Org is an actual
>> > property of ApplicatoinUser.
>> >
>> > So, in (1), OrganizationUser is-a ApplicatoinUser, in (2)
>> ApplicatoinUser
>> > has-a OrganizatoinUser
>> >
>> >
>> > Obviously (1) is gonna be much easier to implement, but (2) is much more
>> > flexible and modular.
>> >
>> >
>> > Here's a sketch of how to implement (2):
>> >
>> >
>> > First, we have the Organization entity:
>> >
>> > public class Organization {
>> >
>> >     // name property etc
>> >     private String name;
>> >     public String getName() { ... }
>> >     public void setName(String name) { ... }
>> >
>> >
>> >
>> >     // 1:m bidir collection of OrganizationUser, hidden
>> >     Persistent(mappedBy="organization")
>> >     private SortedSet<OrganizationUser> users;
>> >
>> >     @Hidden
>> >     public SortedSet<OrganizationUser> getUsers() { ... }
>> >     public void setUsers(SortedSet<OrganizationUser> users) { ... }
>> >
>> >
>> >
>> >     // 1:m derived collection of ApplicationUsers
>> >     @NotPersisted
>> >     @NotPersistent
>> >     public List<ApplicationUser> getApplicationUsers() {
>> >         return Lists.newArrayList(
>> >                    Iterables.transform(getUsers(),
>> > OrganizationUser.AS_USER));
>> >     }
>> >
>> > }
>> >
>> >
>> >
>> > Next, we have our OrganizatonUser, the tuple between Org and AppUser:
>> >
>> > public class OrganizationUser {
>> >
>> >     public static Function<OrganizationUser, ApplicationUser> AS_USER =
>> >         new Function<OrganizationUser, ApplicationUser>() {
>> >             public ApplicationUser apply(OrganizationUser ou) {
>> >                 return ou.getApplicationUser();
>> >             }
>> >         };
>> >
>> >
>> >     // the org (other side of the 1:m bidir relationship, see above)
>> >     private Organization organization;
>> >     public Organization getOrganization() { ... }
>> >     public void setOrganization(Organization o) { ... }
>> >
>> >
>> >     // the corresponding appUser
>> >     private ApplicationUser applicationUser;
>> >     public ApplicationUser getApplicationUser() { ... }
>> >     public void setApplicationUser(ApplicationUser au) { ... }
>> >
>> > }
>> >
>> >
>> > Next, we have a service that will contribute:
>> > - 'organization' as a property to applicationUser
>> > - 'assignTo' as an action on applicationUser
>> >
>> >
>> > @DomainService
>> > public class OrganizationContributions {
>> >
>> >     @NotInServiceMenu
>> >     @ActionSemantics(As.SAFE)
>> >     @NotContributed(As.ACTION) // ie contributed as property
>> >     public Organization getOrganization(ApplicationUser appUser) {
>> >         OrganizationUser orgUser = organizationUsers.findFor(appUser);
>> >         return orgUser != null? orgUser.getOrganization(): null;
>> >     }
>> >
>> >     @NotInServiceMenu
>> >     public ApplicationUser assignTo(ApplicationUser appUser,
>> Organization
>> > organization) {
>> >         organizationUsers.create(organization, appUser);
>> >         return appUser;
>> >     }
>> >
>> >     @Inject
>> >     private OrganizationUsers organizationUsers;
>> >
>> > }
>> >
>> >
>> > This delegates to an OrganizationUsers repo:
>> >
>> >
>> > @DomainService
>> > public class OrganizationUsers {
>> >
>> >     @Programmatic
>> >     public OrganizationUser findFor(ApplicationUser appUser) {
>> >         return firstMatch(OrganizationUser.class,
>> "findByApplicationUser",
>> > "applicationUser", appUser);
>> >     }
>> >
>> >     @Programmatic
>> >     public OrganizationUser create(Organization org, ApplicationUser
>> > appUser) {
>> >         OrganizationUser ou =
>> newTransientInstance(OrganizationUser.class);
>> >         ou.setOrganization(org);
>> >         ou.setApplicationUser(appUser);
>> >         persist(ou);
>> >         return ou;
>> >     }
>> > }
>> >
>> >
>> >
>> > The last bit of the puzzle is handling any deletions.  For this we can
>> make
>> > the security module emit an appropriately strongly typed event, and then
>> > subscribe to it:
>> >
>> > @DomainService
>> > public class OrganizationSubscriptions {
>> >
>> >     @Programmatic
>> >     @PostConstruct
>> >     public void postConstruct() {
>> >         eventBusService.register(this);
>> >     }
>> >
>> >     @Subscribe
>> >     public void on(ApplicationUser.Deleted ev) {
>> >         if(ev.getPhase() == Phase.EXECUTING) {
>> >             ApplicationUser appUser = ev.getApplicationUser();
>> >             OrganizationUser orgUser =
>> organizationUsers.findFor(appUser);
>> >             if(orgUser != null) {
>> >                 // delete
>> >                 removeIfNotAlready(orgUser);
>> >             }
>> >         }
>> >     }
>> >
>> >     @Inject
>> >     private EventBusService eventBusService;
>> > }
>> >
>> >
>> > ~~~~~~~
>> > Of these two approaches, I would imagine you'll probably go with (1),
>> but
>> > I'll update the security module so that either can be done.
>> >
>> > HTH
>> > Dan
>> >
>> >
>> > On 20 November 2014 16:11, Jeroen van der Wal <[email protected]>
>> wrote:
>> >
>> > > Martin:
>> > > Thanks for the compliments and keep us updated on your progress.
>> > >
>> > > Oscar:
>> > > Dan and I are on Holiday too: speaking at ApacheCon. Fortunately for
>> us
>> > > laptops are obliged here :-)
>> > >
>> > > All good stuff that you mentioned, send more when you have time, a
>> domain
>> > > model maybe. As the security module is very fresh with little users It
>> > > shouldn't be hard to refactor it to accommodate more scenarios. Apache
>> > > Fortress is also acting in this space but I don't want to bring in an
>> > > additional component at this stage. But we might want to "borrow"
>> some of
>> > > their concepts.
>> > >
>> > > Cheers,
>> > >
>> > > Jeroen
>> > >
>> > >
>> > >
>> > > On Thu, Nov 20, 2014 at 2:23 PM, GESCONSULTOR <[email protected]
>> >
>> > > wrote:
>> > >
>> > > > Hi all!
>> > > >
>> > > > I'm following the thread with a lot of interest.
>> > > >
>> > > > Problem is that this week I'm on holidays without access to the
>> laptop
>> > > > (first time ever and it's being great :)
>> > > >
>> > > > I find some points here, nearly all them mentioned before:
>> > > > - The need for a Tenant / Tenancy entity.
>> > > > - The need for an interface or abstract base entity that allows to
>> know
>> > > > the Tenant associated with an entity.
>> > > > - the need for the concept of "ownership", that in our case could be
>> > > > associated at least with a role (and perhaps with a specific user?
>> If
>> > > > that's the case perhaps a common abstract parent entity for
>> > > > User and Role should be needed).
>> > > > - and probably the need for Role compositions (parent-child
>> > relationships
>> > > > or preferably m-n relationships - extended RBAC- for nested roles).
>> > > > - A property like "ownerByDefault" or similar that should reference
>> the
>> > > > owning Role (or User?) assigned by default to any entity created by
>> > this
>> > > > user (it could be changed or not afterwards depending on business
>> > logic).
>> > > >
>> > > > Adding something like that to current great implementation should
>> allow
>> > > > for easy (and really fine-grained) domain security.
>> > > >
>> > > > I don't have access to my list of other implementations so it could
>> > > change
>> > > > a bit, but basically that was the basis.
>> > > >
>> > > > HTH,
>> > > >
>> > > > Oscar
>> > > >
>> > > >
>> > > >
>> > > > > El 20/11/2014, a las 6:22, Jeroen van der Wal <
>> [email protected]>
>> > > > escribió:
>> > > > >
>> > > > > Hi Martin B,
>> > > > >
>> > > > > We added Tenancy to the security module which, in our case,
>> > represents
>> > > a
>> > > > > different legal entity and a users are assigned to a tenancy.
>> We've
>> > > > looked
>> > > > > at RBAC [1] but were very pragmatic while implementing the module
>> ;-)
>> > > > > There's certainly room for improvement so if you can share your
>> > > thoughts,
>> > > > > requirements or entity model here we can perhaps align efforts.
>> > > > >
>> > > > > Oscar Bou, one of our other committers was very keen on this
>> subject
>> > > too.
>> > > > > Oscar: perhaps you want to pitch in too?
>> > > > >
>> > > > > And yes, please you can always fork it!
>> > > > >
>> > > > > Cheers,
>> > > > >
>> > > > > Jeroen
>> > > > >
>> > > > > [1] http://en.wikipedia.org/wiki/Role-based_access_control
>> > > > >
>> > > > >
>> > > > >
>> > > > >
>> > > > >
>> > > > > On Thu, Nov 20, 2014 at 9:48 AM, Martin Balmaceda <
>> > > > > [email protected]> wrote:
>> > > > >
>> > > > >> Im not sure how using a Shiro role would work since they are
>> > > predefined
>> > > > yet
>> > > > >> organizations can be added/removed dynamically
>> > > > >>
>> > > > >> On Thu, Nov 20, 2014 at 10:37 AM, Martin Grigorov <
>> > > [email protected]
>> > > > >
>> > > > >> wrote:
>> > > > >>
>> > > > >>> Hi,
>> > > > >>>
>> > > > >>> I am not familiar with isis security module but isn't it
>> possible
>> > to
>> > > > use
>> > > > >> a
>> > > > >>> (Shiro) Role as an Organization ?
>> > > > >>>
>> > > > >>> Martin Grigorov
>> > > > >>> Wicket Training and Consulting
>> > > > >>> https://twitter.com/mtgrigorov
>> > > > >>>
>> > > > >>>> On Thu, Nov 20, 2014 at 10:31 AM, <
>> [email protected]>
>> > > > wrote:
>> > > > >>>>
>> > > > >>>>
>> > > > >>>>
>> > > > >>>>
>> > > > >>>> - Hi Martin, maybe you can try a solution that I made and that
>> > works
>> > > > >> for
>> > > > >>>> me at the moment;
>> > > > >>>> I defined a 'an abstrat secure object' that has the properties
>> you
>> > > are
>> > > > >>>> looking for [1]
>> > > > >>>>
>> > > > >>>> [1]
>> > > > >>
>> > > >
>> > >
>> >
>> https://github.com/johandoornenbal/matching/blob/master/dom/src/main/java/info/matchingservice/dom/MatchingSecureMutableObject.java
>> > > > >>>>
>> > > > >>>> Thanks I agree, option 1 is much better.
>> > > > >>>>
>> > > > >>>> As for my user case: I have a system that hosts a number or
>> > > > >> organizations
>> > > > >>>> orthogonally. What I need to do is associate each user to
>> exactly
>> > 1
>> > > > org
>> > > > >>> so
>> > > > >>>> that he/she can only see and modify information belonging to
>> that
>> > > org.
>> > > > >>>>
>> > > > >>>> After looking at the problem, I figure that the best way to do
>> it
>> > > > would
>> > > > >>> be
>> > > > >>>> to use the security module and add an Organization property to
>> > > > >>>> ApplicationUser. Unfortunately it seems I would have to fork
>> the
>> > > > module
>> > > > >>> and
>> > > > >>>> add my custom Orgnization domain object to it.
>> > > > >>>>
>> > > > >>>>
>> > > > >>>>
>> > > > >>>>
>> > > > >>>>
>> > > > >>>> On Wed, Nov 19, 2014 at 5:54 PM, Dan Haywood
>> > > > >>>> wrote:
>> > > > >>>>
>> > > > >>>>>> On 19 November 2014 16:41, Jeroen van der Wal  wrote:
>> > > > >>>>>>
>> > > > >>>>>> Just double-checked: the master branch of
>> isis-module-security
>> > > uses
>> > > > >>> the
>> > > > >>>>>> latest and greatest version of Isis, 1.8.0-SNAPSHOT
>> > > > >>>>>>
>> > > > >>>>>> [1]
>> > > > >>
>> > > >
>> > >
>> >
>> https://github.com/isisaddons/isis-module-security/blob/master/pom.xml#L32-L36
>> > > > >>>>> (though the screenshots in the README are still of 1.7.0)
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>> On Wed, Nov 19, 2014 at 4:33 PM, Jeroen van der Wal  >
>> > > > >>>>>> wrote:
>> > > > >>>>>>
>> > > > >>>>>>> Hi Martin,
>> > > > >>>>>>>
>> > > > >>>>>>> I would advice against option 2 because you lose an easy
>> update
>> > > > >>> path
>> > > > >>>> to
>> > > > >>>>>>> newer versions of the security module.
>> > > > >>>>>
>> > > > >>>>> +1 to that advice.
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>>> Tell us more about your use-case so we can see what the
>> options
>> > > > >>> are.
>> > > > >>>>>
>> > > > >>>>> In particular, is the additional information you need to store
>> > > > >>> mandatory
>> > > > >>>>> with no sensible default (ie would need to prompt for it), or
>> > would
>> > > > >> the
>> > > > >>>>> current signatures of the methods in ApplicationUsers domain
>> > > service
>> > > > >>>>> suffice?
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>
>> > > > >>>>>>> Cheers,
>> > > > >>>>>>>
>> > > > >>>>>>>
>> > > > >>>>>>> Jeroen
>> > > > >>>>>>>
>> > > > >>>>>>> On Wed, Nov 19, 2014 at 2:24 PM, Martin Balmaceda <
>> > > > >>>>>>> [email protected]> wrote:
>> > > > >>>>
>> > > > >>>>
>> > > > >>>>
>> > > > >>>> --
>> > > > >>>> to do is to be. dobedobedo
>> > > > >>
>> > > > >>
>> > > > >>
>> > > > >> --
>> > > > >> to do is to be. dobedobedo
>> > > > >>
>> > > >
>> > >
>> >
>>
>>
>>
>> --
>> to do is to be. dobedobedo
>>
>

Reply via email to