TireSwingSoftware/openassign-server — Issue #107: Add support for authorizing Manager method calls
Author: jc0n
Created: 2012-02-24 00:53:55+00:00
State: open
Labels: feature

Currently an arbitrary permission is all-or-nothing for a given role (with the exception of authorizer methods that do not rely on the actee). It would be helpful to be able to assign arbitrary permissions along with method checks which include some logic which may decide given a context whether permission is granted or denied.

We can support authorization using more than just model objects as the Actee, we can use Manager objects as the actee and authorize method calls.

-----

A rough mockup of the concept is as follows:

```python
methods = {'name': 'some_foo_method_authorizer'}
crud = {
# preserve existing functionality for model objects
'User': {
#....
}
'UserManager': {
'method': 'foo_method' # gives privilege to call foo_method whatever that entails
}
}
```
Meanwhile... in the authorizer

```python
class Authorizer(object):
#....
# note: the method signiture does not use *args, and **kwargs in order to keep the
# arguments passed to check_method_call separate from the arguments
# being used in the method being authorized.
def check_method_call(self, auth_token, manager, method_name, args=(), kwargs={}):
"""Check that a user is authorized to call a manager method
named `method_name` on the `manager` object instance.""""
# do special authorization stuff

def foo_method_authorizer(self, auth_token, actee, args, kwargs):
if not isinstance(actee, UserManager):
raise InvalidActeeTypeException()
```
Meanwhile...in the UserManager

```python

class UserManager(ObjectManager):
#...
@authorize # would wrap the following with a call to
# self.authorizer.check_method_call(auth_token, self, 'foo_method, args=args, kwargs=kwargs')
@service_method
def foo_method(self, auth_token, some, args):
pass
```

Benefits of this approach:

- Cut down on use of arbitrary permissions for the sake of allowing a single method operation

- With the method permissions included in the crud, it will be more human readable as to which permissions a given role has.

- Method calls can be authorized with more sophisticated authorize methods.

-----

Some additional notes:

In #49 the following description characterizes the use case perfectly:

> For now, a user is authorized to do this if they are an Admin. Also, if the Task is a SURR, anyone with the role Instructor for the same session can send an email.

For this particular case it would be nice to abstract the authorization into an authorizer method vs. in the function call itself. Currently I'm not sure how else to authorize such a check given that ultimately sending an email isnt one of C,R,U or D operations.

If it is done as an arbitrary permission there will be code within the method to handle the Instructor case (which seems to defeat the purpose of such checks remaining in the authorizer). Also if another user needs to perform the operation it is much easier to add it to the respective role rather than alter the method implementation.