views:

110

answers:

3

Hello,

I have a multilingual Django project. Every language is a different subdomain. So we've decided to use the "sites" application and to create one different site for every language.

On that project, I also have a "pages" application, which is quite similar to a CMS. The user can create pages with content and they'll be displayed in the appropriate language site.

Now I'm looking to be able to manage advanced permissions. What I need to do is to allow, in the admin application a user only to create and update pages for one (or many) specific language/site.

What'd be the cleaner way to do something like that ?

Edit : Here is the solution I've adapted, given by Chris

I create a decorator that's checking if the user is appropriately in the group that has access to the lang. See Chris' accepted answer for an example of this.

In a "normal" view, I do the following :

def view(self):
    # Whatever you wanna do
    return render_to_response('page.html', {}, RequestContext(request))
view = group_required(view)

If the user is in the group, it'll return the method. Otherwise, it'll return an "Access Denied" error.

And in my admin, I do the following :

class PageAdmin(admin.ModelAdmin):
    list_display = ('title', 'published')    
    fieldsets = [
        (None, {'fields': ['title', 'slug', 'whatever_field_you_have']}),
    ]

    def has_add_permission(self, request):
        return in_group_required(request)
admin.site.register(Page, PageAdmin)

Where the in_group_required is a similar method to group_required mentionned above. But will return only true or false depending of if we have access or not.

And because we use them quite much in the previous examples, you'll find above here what I have in my in_group and group_required methods.

def group_required(func):
    def _decorator(request, *args, **kwargs):
        if not in_group(request):
            return HttpResponse("Access denied")
        return func(*args, **kwargs)
    return _decorator

def in_group(request):
    language = Language.objects.get(site__domain__exact=request.get_host())
    for group in language.group.all():
        if request.user in group.user_set.all():
            return True
    return False
+3  A: 

You could create a Group (http://docs.djangoproject.com/en/dev/topics/auth/) per site / language and add the users to the groups accordingly.

Then, you can check if the request.user.groups belongs to the group. (You can do this with a decorator:

def group_required(func):
    def _decorator(request, *args, **kwargs):
        hostname = request.META.get('HTTP_HOST')
        lang = hostname.split(".")[0]
        if not lang in request.user.groups:
            return HttpResponse("Access denied")
        return func(*args, **kwargs)
    return _decorator

(Correct / modify the code to match your requirements...)

Chris
Interesting idea. Would be easy to implement in a "normal" view. But I need to filter the permissions in the admin application. How can I implement that there ?
Damien MATHIEU
+1  A: 

You can override has_add_permission (and related methods) in your ModelAdmin class. (With similar code like shown above)

Chris
Yay ! I didn't know about has_add_permission :)Thanks. I edit my first post with the code.
Damien MATHIEU
A: 

If you want to filter the Page objects on the admin index of your page-application, you can override the method queryset() in ModelAdmin. This QuerySet returns only those Page objects, that belong to a Site (and therefore Group) of which the request.user is a member.

Pages.objects.filter(site__name__in=request.user.groups)
Chris
Chris - could you edit your three answers into one final answer? It's a bit hard to follow as it is.
Dominic Rodger
It's not really one or a final solution. But I'll sumarize:The key point is to have a Group per Site and add Users accordingly.The first answer shows a decorator for "normal views".The second answer modifies the has_add_permission method of the ModelAdmin class which leads to the effect, that the User (request.user) can only add a Page on the "current Site", when he's in the right group.The third answer is about modification of the QuerySet for index page the application's admin interface. Only Pages that belong to a Site/Group in which the request.user is, are shown.
Chris
@Chris the last part of my question is actually the answer. As Dominic Rodger said, it's pretty hard to follow your replies as they are here.I've found exactly what I needed with has_add_permissions and the decorator. Thanks.
Damien MATHIEU