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 >> >
