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 <jer...@stromboli.it> 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 <o....@gesconsultor.com>
> 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 <jer...@stromboli.it>
> > 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 <
> > > martin.balmac...@gmail.com> 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 <
> mgrigo...@apache.org
> > >
> > >> 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, <johandoornen...@filternet.nl>
> > 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 <
> > >>>>>>> martin.balmac...@gmail.com> wrote:
> > >>>>
> > >>>>
> > >>>>
> > >>>> --
> > >>>> to do is to be. dobedobedo
> > >>
> > >>
> > >>
> > >> --
> > >> to do is to be. dobedobedo
> > >>
> >
>

Reply via email to