Login

Owner required decorator

Author:
polarbear
Posted:
July 11, 2008
Language:
Python
Version:
.96
Tags:
decorator
Score:
3 (after 3 ratings)

This decorator allows edit or delete for the owner of the record. Snippet applies for every model that has ForeignKey to User. Works for User model too. Works with other decorators as permission_required or similar.

Decorator raise http 403 view if user is not owner.

Usage

@permission_required('blogs.change_entry')
@owner_required(Entry)
def manage_entry(request, object_id=None, object=None):

Decorator populates object kwargs if object_id present, otherwise just returns original view function.

@permission_required('blogs.delete_entry')
@owner_required()
def entry_delete(*args, **kwargs):
    kwargs["post_delete_redirect"] = reverse('manage_blogs')
    return delete_object(*args, **kwargs)

In generic delete wrapper view returns original view function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def owner_required(Model=None):
    """
    Usage:
    
    @permission_required('blogs.change_entry')
    @owner_required(Entry)
    def manage_entry(request, object_id=None, object=None):
    
    @permission_required('blogs.delete_entry')
    @owner_required()
    def entry_delete(*args, **kwargs):
        kwargs["post_delete_redirect"] = reverse('manage_blogs')
        return delete_object(*args, **kwargs)
    """
    def _decorator(viewfunc):
        def _closure(request, *args, **kwargs):
            user = request.user
            grant = False
            model = Model
            mod_edit = False
            if 'object_id' in kwargs:
                object_id = int(kwargs['object_id'])
                if model:
                    mod_edit = True
                elif 'model' in kwargs:
                    model = kwargs['model']
                object = get_object_or_404(model, pk=object_id)
                
                if user.is_superuser:
                    grant = True
                else:
                    if user.__class__ == model:
                        grant = object_id == user.id
                    else:
                        names = [rel.get_accessor_name() for rel in user._meta.get_all_related_objects() if rel.model == model]
                        if names:
                            grant = object_id in [o.id for o in eval('user.%s.all()' % names[0])]
                if not grant:
                    response = render_to_response("403.html", {'object': object}, context_instance=RequestContext(request))
                    response.status_code = 403
                    return response
                if mod_edit:
                    kwargs['object'] = object
                
            response = viewfunc(request, *args, **kwargs)
            return response
        
        return wraps(viewfunc)(_closure)
    return _decorator

More like this

  1. Other approach of making middleware (by decorators) by diverman 4 years ago
  2. PK->objects in view signature by AdamKG 6 years, 12 months ago
  3. object-oriented generic views by carljm 6 years, 7 months ago
  4. Wrapper-function Pattern by Archatas 4 years, 11 months ago
  5. View Permission Decorator Helper by jgeewax 6 years, 8 months ago

Comments

phxx (on August 7, 2008):

Cool idea, but i think the eval statement is not necessary. You could use also getattr instead:

getattr(user, names[0]).all()

#

Please login first before commenting.