#########################
# models.py
#########################
from django.db import models
from django.contrib.flatpages.models import FlatPage
from django.contrib.auth.models import User

class Permission(models.Model):
    '''
    A mapping of Flatpage URLs to Users. 
    NOTE: for this to work, the user must already have 
    permissions to edit FlatPages.
    '''
    url = models.CharField(max_length=255, \
        help_text='The selected Users will be able to edit all FlatPages \
        that begin with this URL. For example: "/johndoe/"')
    users = models.ManyToManyField(User, related_name="flatpagepermission")

    def __unicode__(self):
        return self.url

    class Meta:
        ordering = ['url', ]

def user_has_flatpage_permission(user, url):
    '''
    A helper function to check to see if the given user has 
    permission to edit the flatpage associated with the given URL.

    user = a django.contrib.auth.models.User object
    url = a URL fragment for a FlatPage. E.g. /about/something/else
    '''
    if user.is_superuser:
        return True

    perms = Permission.objects.filter(users=user)
    for p in perms:
        if url.startswith(p.url):
            return True
    return False

#########################
# admin.py
#########################
from flatpage_addons.models import Permission
from django.contrib import admin

class PermissionAdmin(admin.ModelAdmin):
    list_display = ('url', )

admin.site.register(Permission, PermissionAdmin)

##################################
# templatetags/flatpage_addons_extras.py
##################################
from django import template
from django.template import Variable, VariableDoesNotExist
from django.contrib.auth.models import User
from de_concierge.flatpage_addons.models import user_has_flatpage_permission
from django.contrib.admin.templatetags import admin_list

register = template.Library()

def results(user, cl):
    '''
    Modified from django.contrib.admin.templatetags.admin_list
    Generates a list of items for the Admin's change_list page.
    This function filters out those FlatPage objects that do 
    for which the current user does not have Permission.
    '''
    for res in cl.result_list:
        if user_has_flatpage_permission(user, res.url):
            yield list(admin_list.items_for_result(cl,res))
            
@register.inclusion_tag('admin/change_list_results.html')
def flatpage_result_list(user, cl):
    ''' 
    Based on django.contrib.admin.templatetag.admin_list.result_list;
    An inclusion tag that omits flatpages that the user 
    does not have permission to edit.
    '''
    return {'cl':cl,
            'result_headers':list(admin_list.result_headers(cl)),
            'results': list(results(user, cl))}

class IfHasFlatPagePermissionNode(template.Node):
    ''' 
    Execute code in this block if the given User has permission to
    the given FlatPage URL. 
    '''
    def __init__(self, user, url, nodelist_true, nodelist_false):
        self.user = Variable(user)
        self.url = Variable(url)
        self.nodelist_true = nodelist_true
        self.nodelist_false = nodelist_false

    def __repr__(self):
        return "<IfHasFlatPagePermissionNode>"

    def render(self, context):
        try:
            user_obj = self.user.resolve(context)
            flatpage_url = self.url.resolve(context)

            if user_has_flatpage_permission(user_obj, flatpage_url):
                return self.nodelist_true.render(context)
        except VariableDoesNotExist:
            pass

        return self.nodelist_false.render(context)

def do_ifhasflatpagepermission(parser, token):
    ''' 
    Parser for Template:
        {% ifhasflatpagepermission <user> <url> %} 
            {# execute contents #}
        {% endifhasflatpagepermission %}
    '''
    bits = list(token.split_contents())
    if len(bits) != 3:
        raise template.TemplateSyntaxError, "%r takes 2 arguments: a User object and a URL."%bits[0]
    end_tag = 'end' + bits[0]
    nodelist_true = parser.parse(('else', end_tag))
    token = parser.next_token()
    if token.contents == 'else':
        nodelist_false = parser.parse((end_tag, ))
        parser.delete_first_token()
    else:
        nodelist_false = template.NodeList()
    return IfHasFlatPagePermissionNode(bits[1], bits[2], nodelist_true, nodelist_false)

# Register the new tag
register.tag('ifhasflatpagepermission', do_ifhasflatpagepermission)


##########################################
# Lastly, we override the change_form.html and the
# change_list.html admin templates for the flatpage app:
# /my_project/templates/admin/flatpages/flatpage/
##########################################

##########################################
# change_form.html
##########################################
{% extends "admin/change_form.html" %}
{% load flatpage_addons_extras %}

{% block content %}
    {% ifhasflatpagepermission user original.url %}
        {{ block.super }}
    {% else %}
        <h1> You do not have permission to Edit this page </h1>
    {% endifhasflatpagepermission %}
{% endblock %}

##########################################
# change_list.html
##########################################
{% extends "admin/change_list.html" %}
{% load adminmedia admin_list i18n %}
{% load flatpage_addons_extras %}

{% block result_list %}
    {# {% result_list cl %} #}
    {% flatpage_result_list user cl %}
{% endblock %}


