Decorators as Guards

I’m exploring a new pattern – I’m sure it’s been done before, but it’s new to me, and a useful exercise to get to the next stage with an application I’m envisioning.  The pattern is using Seaside Decorators as security guards.

So, last night, finally squeezed in enough time to my decorator guards into action.  Happy to report they’re working fine.  You can review the demo app yourself at agoric.seasidehosting.st/seaside/ibis .  Login as bob@test.com, password bob, or alice@test.com, password alice.

I’m not completely proud of this code – it’s a quick hack, needs some refactoring.  And, cosmetics are not pretty – will need to do some CSS prettifying soon.  The “guard” itself takes a traditional, ACL-lookup approach to security, and I’d like to refactor that to more of a capabilities approach, but ACLs work fine for now: straightforward, familiar and easy to understand.  Here’s what the Guard itself look like:

WADecoration subclass: #IBSecEditGuard
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'IBIS'

renderContentOn: html
"if usr has access rights, render appropriate action buttons, then render object itself"

	html div class: 'editframe';style: 'margin-left: ',(self owner level *3) asString, 'em';
	with: [
	self userIsEditor ifTrue: [
		html span class: 'cmd'; with: [
			html anchor callback: [ self edit]; with: 'edit'.]].
		html space.
	   self renderOwnerOn: html]

userIsEditor
	^(self editorsfordoc contains: self session user)
	  or: [self session user = self owner doc author]

canedit

	^(self allowededitors contains: self session user)

editorsfordoc
	^ IBSecGuard editorsfordoc: self owner doc

edit
	self owner edit

To deploy the guard, add it as a decorator to an appropriate view, using addDecoration:.

IBISDocView>>initialize

	super initialize.
	myEditor := IBISDocumentEditor new.
	myLevel := 0.
	self addDecoration: IBSecEditGuard new.

IBISDocView>>renderContentOn: html
        html span class: 'cmd'; with: [html anchor callback: [self answer: true]; with: 'back'].
        html div class: 'doc';
           with:
              [html paragraph class: 'title';
                  with: [html text: myDoc type, ': ', myDoc title.
                           html span class: 'author'; with: ' (',myDoc author userName,')'].
               html paragraph class: 'text'; with: [html text: myDoc text].
].

So, the view here is not at all concerned with security. It renders the object (myDoc) visible, and has a pointer to the document’s editor view, but doesn’t involve itself in whether a user has edit access or not – that’s the Decorator’s job. Security, like persistence and logging, are typical application needs, and it’s nice to provide an external framework to provide those services, instead of intermingling security with presentation with business logic code. My demo here provides security with the one line addition of a Decorator object, and that object itself is just around 10 lines of code.

As I mentioned, this is still just a hack; there’s some refactoring that will be welcome, and I’ll likely abandon the ACL approach in favor of a more capabilities-oriented approach; and, I envision a more general way of visually adding “commands” (like the edit anchor link) to the Decorator view, in such a way that it can support multiple command links, in a chain of decorators … but this is a good start.

Published by

kevin

I'm the founder of Agoric Source, co-organizer of the Houston Python Meetup, director of technology at Newspaper Subscription Services, LP, technology advisor to InstaFuel, active board member of the Houston Area Model United Nations, and occasional volunteer to the Red Cross (during hurricanes or other local emergencies). I'm first and foremost still a software hacker, but with my economics background and business experience, I serve well as a project or program manager, technical visionary, etc.