Login

Owner required decorator

Author:
polarbear
Posted:
July 11, 2008
Language:
Python
Version:
.96
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. Template tag - list punctuation for a list of items by shapiromatron 10 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 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.