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