We solved this a number of ways, depending upon particular context within our app. Acegi was unable to satisfy all of our security requirements, so we went with a custom solution from top to bottom, and one of our requirements was identical to yours. The set of roles and per-page permission for each role are loaded into a data structure rather than parsed out of the page specification, in our case. This gives us the benefit of being able to use permissions without redeploying the app. You could choose to populate your data structure via a declarative environment such as a spring context, hivemind config, external config file, database, etc, so it is pretty flexible in that regard. In our case, the data structure is a spring bean which is injected into the page and then passed into components via a parameter.
Within tapestry, we implemented the following - There's an AuthorizationDelegate injected into any page which is accessed within the pageValidate method. It checks the currently logged-in user and its assigned roles against the roles allowed to load the page (and in our case, a mode - read or write). If they fail auth, they are redirected away. Within templates, we use a tag <IfAuth> which can conditionally include parts of a template based on whether a user is authorized to see a section (we actually have per-property r/w permissions on each entity, so every form field is wrapped in an IfAuth tag, usually within a subclass of the original tapestry component). We have subclassed ExternalLink and PageLink so that if the current user is not authorized, the link renders differently (and we have various modes, depending upon context). Our IfAuth tag actually works much like if/elseif/else in that you can cascade through conditionals depending upon how previous conditions evaluated. This allows us to have alternative renditions of a template area based on granted permission. Since we have read/write permissions on individual properties of entities in the ui based on role, but we also have per-entity read/write permissions assigned to individual users, we really weren't able to use Acegi. Acegi wanted us to do lots of things up in the service layer that were far more effectively handled down in the data mapping layer. We use hibernate filters to ensure that only objects assigned to the current user are loaded, modified, or stored. We use an AOP interceptor to inject the appropriate filters on any service method calls. All that necessitated a non-Acegi solution, which just couldn't do what we wanted efficiently. By using filters and AOP and subclassing various input field components, we were able to make very minimal changes to the service or data access layers and kept changes to our ui layer to a bare minimum (the entire security layer was added on after initial application development, since it was not spec'd before we had to have the first internal-use-only release out the door). I can think of cleaner solutions if I was building an app to support that security model from scratch, but our solution wound up being very flexible with minimal invasiveness into an existing app. To be honest, the saving grace for our app was that, because we had very consistent layout for each input component, we created a wrapper component which would determine the type of input field to render based on the type of the property that was bound to it (Kind of like BeanForm, but for an individual property instead of an entire Bean, giving us more control over layout and ajax fanciness). Booleans get checkboxes, lists get select drop downs or palettes, strings get textboxes, etc. This enabled us to just throw an IfAuth tag around the entire template contents for the wrapper component in order to conditionally include a field based on role permissions. With that single tag, we were able to apply role-based authorization to about 85% of our application. Slapping IfAuth tags around individual menu items in the main menu took us to about 95%. The remaining 5% consisted of fields which didn't use our wrapper component and required individual IfAuth conditionals and links which were modified to use subclass versions of the link components that conditionally include the link depending upon authorization. We are now free to build a UI to modify the permissions data structure on the fly, which is also very useful to our organization. --sam On 1/30/07, Hugo Palma <[EMAIL PROTECTED]> wrote:
Ok. If you really want to go ahead with page spec parsing i guess you can use the servlet context to find the spec file and then you'll have to parse it yourself. You can inject the servlet context adding this to your pages base class: @InjectObject("service:tapestry.globals.ServletContext") public abstract ServletContext getServletContext(); Robert J. Walker wrote: > Yeah, we've been considering Acegi, but that's a little more long-range. The only issue I have with using annotations for this is that I would have to create a class for every page in the app. As it stands right now, I'm able to reuse the same class for a fair number of my simpler pages without having a subclass for each one. > > Robert J. Walker > > -----Original Message----- > From: Hugo Palma [mailto:[EMAIL PROTECTED] > Sent: Monday, January 29, 2007 4:53 PM > To: Tapestry users > Subject: Re: Reading page specifications... *without* loading the page > > > Without really answering your question, have you looked at > tapestry-acegi (http://www.carmanconsulting.com/tapestry-acegi/). > The Secured annotation is a life saver...... > > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > >
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]