Access control example

Fields and Events can be set up with special methods that the framework can call in order to determine what rights the current user has regarding the Field or Event. There are two kinds of rights: whether one can read or write the item.

An Input will only be visible and editable if the user is allowed to read and write the Field to which the Input is linked. A Field that is readable but not writable will cause an Input to be visible but greyed out. If the Field is not readable and also not writable to a user, it will not appear on Views shown to that user.

The access rights of an Event influence a Button linked to it similarly to how the access rights on a Field control the display of an Input linked to it.

The example program presented here renders a single page with an input and a button. Each of these elements are restricted in some way:

  • The input labelled Greyed out is for a Field that is allowed to be read but not written (ie, changed).
  • The Greyed out button is greyed out for similar reasons: the user may see the button, but is not allowed to execute its action.
An screenshot showing a greyed out input and disabled buttons.

Notice in the code below that one specifies an Action for the framework to call in order to determine whether a Field is readable or writable. These Actions should return True or False to indicate whether the user has the corresponding right or not, respectively.

Methods can be marked as @secured. A secured method is adorned with other methods which are called to establish whether the secured method is allowed to be read or written respectively. (These check methods should return True if the right is allowed, else False.)

An Event can infer its access rights directly from the access rights applicable to the method used as its action.

If a programmer somehow mistakenly does call such a secured method when it is not allowed, an exception will be raised.

from __future__ import unicode_literals
from __future__ import print_function
from reahl.web.fw import UserInterface
from reahl.web.ui import TwoColumnPage, Form, TextInput, Button, LabelledBlockInput
from reahl.component.modelinterface import Action
from reahl.component.modelinterface import EmailField
from reahl.component.modelinterface import Event
from reahl.component.modelinterface import exposed
from reahl.component.modelinterface import secured



class AccessUI(UserInterface):
    def assemble(self):
        self.define_view('/', title='Access control demo', page=HomePage.factory())


class HomePage(TwoColumnPage):
    def __init__(self, view):
        super(HomePage, self).__init__(view, style='basic')
        self.main.add_child(CommentForm(view))


class Comment(object):
    def always_allowed(self):
        return True

    def never_allowed(self):
        return False

    @exposed
    def fields(self, fields):
        fields.greyed_out_field = EmailField(label='Greyed out',
                                             default='some default value',
                                             readable=Action(self.always_allowed),
                                             writable=Action(self.never_allowed))

    @exposed
    def events(self, events):
        events.greyed_out_event = Event(label='Greyed out button', action=Action(self.do_something))

    @secured(read_check=always_allowed, write_check=never_allowed)
    def do_something(self): 
        pass


class CommentForm(Form):
    def __init__(self, view):
        super(CommentForm, self).__init__(view, 'myform')

        comment = Comment()
        self.add_child( LabelledBlockInput(TextInput(self, comment.fields.greyed_out_field)) )

        self.define_event_handler(comment.events.greyed_out_event)
        self.add_child( Button(self, comment.events.greyed_out_event) )

Previous topic

Persistence

Next topic

Security considerations