#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

import os
import logging
from urllib import basejoin
from cStringIO import StringIO
from collections import defaultdict
from xml.etree import ElementTree as ET
from copy import copy

import pkg_resources
from tg import expose, redirect, flash, validate
from tg.decorators import without_trailing_slash
from tg import config as tg_config
from pylons import request, app_globals as g, tmpl_context as c
from paste.deploy.converters import asbool, asint
from bson import ObjectId
from bson.errors import InvalidId
from formencode import validators as V
from webob import exc
from formencode import validators as fev

from ming.orm import session
from ming.utils import LazyProperty
import ew.jinja2_ew as ew

from allura.lib import helpers as h
from allura.lib.security import has_access, require_access
from allura import model
from allura.controllers import BaseController
from allura.lib.decorators import require_post, memoize
from allura.lib.utils import permanent_redirect, ConfigProxy
from allura import model as M
from allura.tasks import index_tasks

log = logging.getLogger(__name__)

config = ConfigProxy(common_suffix='forgemail.domain')


class ConfigOption(object):

    """Definition of a configuration option for an :class:`Application`.

    """

    def __init__(self, name, ming_type, default,
                 label=None, help_text=None, validator=None,
                 extra_attrs=None):
        """Create a new ConfigOption."""
        self.name, self.ming_type, self._default, self.label = (
            name, ming_type, default, label or name)
        self.help_text = help_text
        self.validator = validator
        self.extra_attrs = extra_attrs

    @property
    def default(self):
        """Return the default value for this ConfigOption.

        """
        if callable(self._default):
            return self._default()
        return self._default

    def validate(self, value):
        if self.validator:
            return self.validator.to_python(value)
        return value

    def render_attrs(self):
        """Return extra_attrs formatted in a way that allows inserting into html tag"""
        return ew._Jinja2Widget().j2_attrs(self.extra_attrs or {})


class SitemapEntry(object):

    """A labeled URL, which may optionally have
    :class:`children <SitemapEntry>`.

    Used for generating trees of links.

    """

    def __init__(self, label, url=None, children=None, className=None,
                 ui_icon=None, small=None, tool_name=None, matching_urls=None, extra_html_attrs=None):
        """Create a new SitemapEntry.

        """
        self.label = label
        self.className = className
        if url is not None:
            url = url.encode('utf-8')
        self.url = url
        self.small = small
        self.ui_icon = ui_icon
        self.children = children or []
        self.tool_name = tool_name
        self.matching_urls = matching_urls or []
        self.extra_html_attrs = extra_html_attrs or {}

    def __getitem__(self, x):
        """Automatically expand the list of sitemap child entries with the
        given items.  Example::

            SitemapEntry('HelloForge')[
                SitemapEntry('foo')[
                    SitemapEntry('Pages')[pages]
                ]
            ]

        TODO: deprecate this; use a more clear method of building a tree

        """
        if isinstance(x, (list, tuple)):
            self.children.extend(list(x))
        else:
            self.children.append(x)
        return self

    def __repr__(self):
        l = ['<SitemapEntry ']
        l.append('    label=%r' % self.label)
        l.append('    url=%r' % self.url)
        l.append('    children=%s' %
                 repr(self.children).replace('\n', '\n    '))
        l.append('>')
        return '\n'.join(l)

    def bind_app(self, app):
        """Recreate this SitemapEntry in the context of
        :class:`app <Application>`.

        :returns: :class:`SitemapEntry`

        """
        lbl = self.label
        url = self.url
        if callable(lbl):
            lbl = lbl(app)
        if url is not None:
            url = basejoin(app.url, url)
        return SitemapEntry(lbl, url, [
            ch.bind_app(app) for ch in self.children],
            className=self.className,
            ui_icon=self.ui_icon,
            small=self.small,
            tool_name=self.tool_name,
            matching_urls=self.matching_urls)

    def extend(self, sitemap_entries):
        """Extend our children with ``sitemap_entries``.

        :param sitemap_entries: list of :class:`SitemapEntry`

        For each entry, if it doesn't already exist in our children, add it.
        If it does already exist in our children, recursively extend the
        children or our copy with the children of the new copy.

        """
        child_index = dict(
            (ch.label, ch) for ch in self.children)
        for e in sitemap_entries:
            lbl = e.label
            match = child_index.get(e.label)
            if match and match.url == e.url:
                match.extend(e.children)
            else:
                self.children.append(e)
                child_index[lbl] = e

    def matches_url(self, request):
        """Return True if this SitemapEntry 'matches' the url of ``request``.

        """
        return self.url in request.upath_info or any([
            url in request.upath_info for url in self.matching_urls])

    def __json__(self):
        return dict(
            label=self.label,
            className=self.className,
            url=self.url,
            small=self.small,
            ui_icon=self.ui_icon,
            children=self.children,
            tool_name=self.tool_name,
            matching_urls=self.matching_urls,
            extra_html_attrs=self.extra_html_attrs,
        )

class Application(object):

    """
    The base Allura pluggable application

    After extending this, expose the app by adding an entry point in your
    setup.py::

        [allura]
        myapp = foo.bar.baz:MyAppClass

    :cvar str status: One of 'production', 'beta', 'alpha', or 'user'. By
        default, only 'production' apps are installable in projects. Default
        is 'production'.
    :cvar bool searchable: If True, show search box in the left menu of this
        Application. Default is True.
    :cvar bool exportable: Default is False, Application can't be exported to json.
    :cvar list permissions: Named permissions used by instances of this
        Application. Default is [].
    :cvar dict permissions_desc: Descriptions of the named permissions.
    :cvar int max_instances: Specifies the number of tools of this type
        that can be added to the project. Zero indicates the system tool or one that
        can not be added to the project by the user. Default value is float("inf").
    :cvar bool hidden: Default is False, Application is not hidden from the
        list of a project's installed tools.
    :cvar bool has_notifications: Default is True, if set to False then application will not
        be listed on user subscriptions table.
    :cvar str tool_description: Text description of this Application.
    :cvar bool relaxed_mount_points: Set to True to relax the default mount point
        naming restrictions for this Application. Default is False. See
        :attr:`default mount point naming rules <allura.lib.helpers.re_tool_mount_point>` and
        :attr:`relaxed mount point naming rules <allura.lib.helpers.re_relaxed_tool_mount_point>`.
    :cvar Controller root: Serves content at
        /<neighborhood>/<project>/<app>/. Default is None - subclasses should
        override.
    :cvar Controller api_root: Serves API access at
        /rest/<neighborhood>/<project>/<app>/. Default is None - subclasses
        should override to expose API access to the Application.
    :cvar Controller admin_api_root: Serves Admin API access at
        /rest/<neighborhood>/<project>/admin/<app>/. Default is None -
        subclasses should override to expose Admin API access to the
        Application.
    :ivar Controller admin: Serves admin functions at
        /<neighborhood>/<project>/<admin>/<app>/. Default is a
        :class:`DefaultAdminController` instance.
    :cvar dict icons: Mapping of icon sizes to application-specific icon paths.
    :cvar list config_on_install: :class:`ConfigOption` names that should be
        configured by user during app installation
    """

    __version__ = None
    config_options = [
        ConfigOption('mount_point', str, 'app'),
        ConfigOption('mount_label', str, 'app'),
        ConfigOption('ordinal', int, '0')]
    config_on_install = []
    status_map = ['production', 'beta', 'alpha', 'user']
    status = 'production'
    script_name = None
    root = None  # root controller
    api_root = None
    admin_api_root = None
    permissions = []
    permissions_desc = {
        'unmoderated_post': 'Post comments without moderation.',
        'post': 'Post comments, subject to moderation.',
        'moderate': 'Moderate comments.',
        'configure': 'Set label and options. Requires admin permission.',
        'admin': 'Set permissions.',
    }
    max_instances = float("inf")
    searchable = False
    exportable = False
    DiscussionClass = model.Discussion
    PostClass = model.Post
    AttachmentClass = model.DiscussionAttachment
    tool_label = 'Tool'
    tool_description = "This is a tool for Allura forge."
    default_mount_label = 'Tool Name'
    default_mount_point = 'tool'
    relaxed_mount_points = False
    ordinal = 0
    hidden = False
    has_notifications = True
    icons = {
        24: 'images/admin_24.png',
        32: 'images/admin_32.png',
        48: 'images/admin_48.png'
    }

    def __init__(self, project, app_config_object):
        """Create an Application instance.

        :param project: Project to which this Application belongs
        :type project: :class:`allura.model.project.Project`
        :param app_config_object: Config describing this Application
        :type app_config_object: :class:`allura.model.project.AppConfig`

        """
        self.project = project
        self.config = app_config_object
        self.admin = DefaultAdminController(self)

    @LazyProperty
    def sitemap(self):
        """Return a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
        describing the page hierarchy provided by this Application.

        If the list is empty, the Application will not be displayed in the
        main project nav bar.

        """
        return [SitemapEntry(self.config.options.mount_label, '.')]

    @LazyProperty
    def url(self):
        """Return the URL for this Application.

        """
        return self.config.url(project=self.project)

    @LazyProperty
    def admin_url(self):
        return '{}{}/{}/'.format(
            self.project.url(), 'admin',
            self.config.options.mount_point)

    @property
    def email_address(self):
        """Return email address for this Application.

        Email address constructed from Application's url, and looks like this:

            wiki@test.p.in.domain.net

        where 'wiki@test.p' comes from app url (in this case /p/test/wiki/)
        and '.in.domain.net' comes from 'forgemail.domain' config entry.

        Assumes self.url returns a url path without domain, starting with '/'
        """
        if self.config.options.get('AllowEmailPosting', True):
            parts = list(reversed(self.url[1:-1].split('/')))
            return '%s@%s%s' % (parts[0], '.'.join(parts[1:]), config.common_suffix)
        else:
            return tg_config.get('forgemail.return_path')

    @property
    def acl(self):
        """Return the :class:`Access Control List <allura.model.types.ACL>`
        for this Application.

        """
        return self.config.acl

    @classmethod
    def describe_permission(cls, permission):
        """Return help text describing what features ``permission`` controls.

        Subclasses should define :attr:`permissions_desc`,
        a ``{permission: description}`` mapping.

        Returns empty string if there is no description for ``permission``.

        """
        d = {}
        for t in reversed(cls.__mro__):
            d = dict(d, **getattr(t, 'permissions_desc', {}))
        return d.get(permission, '')

    def parent_security_context(self):
        """Return the parent of this object.

        Used for calculating permissions based on trees of ACLs.

        """
        return self.config.parent_security_context()

    @property
    def installable(self):
        """Checks whether to add a tool to the project.

        Return True if app can be installed.

        :rtype: bool

        """
        return self._installable(self.config.tool_name,
                                 self.project.neighborhood,
                                 self.project.app_configs,
                                 )

    @classmethod
    def _installable(cls, tool_name, nbhd, project_tools):
        if tool_name.lower() in nbhd.get_prohibited_tools():
            return False
        tools_list = [tool.tool_name.lower() for tool in project_tools]
        return tools_list.count(tool_name.lower()) < cls.max_instances

    @classmethod
    def validate_mount_point(cls, mount_point):
        """Check if ``mount_point`` is valid for this Application.

        In general, subclasses should not override this, but rather toggle
        the strictness of allowed mount point names by toggling
        :attr:`Application.relaxed_mount_points`.

        :param mount_point: the mount point to validate
        :type mount_point: str
        :rtype: A :class:`regex Match object <_sre.SRE_Match>` if the mount
                point is valid, else None

        """
        re = (h.re_relaxed_tool_mount_point if cls.relaxed_mount_points
              else h.re_tool_mount_point)
        return re.match(mount_point)

    @classmethod
    def status_int(self):
        """Return the :attr:`status` of this Application as an int.

        Used for sorting available Apps by status in the Admin interface.

        """
        return self.status_map.index(self.status)

    @classmethod
    def icon_url(cls, size):
        """Return URL for icon of the given ``size``.

        Subclasses can define their own icons by overriding
        :attr:`icons`.

        """
        resource, url = cls.icons.get(size), ''
        if resource:
            resource_path = os.path.join('nf', resource)
            url = (g.forge_static(resource) if cls.has_resource(resource_path)
                   else g.theme_href(resource))
        return url

    @classmethod
    @memoize
    def has_resource(cls, resource_path):
        """Determine whether this Application has the resource pointed to by
        ``resource_path``.

        If the resource is not found for the immediate class, its parents
        will be searched. The return value is the class that "owns" the
        resource, or None if the resource is not found.

        """
        for klass in [o for o in cls.__mro__ if issubclass(o, Application)]:
            if pkg_resources.resource_exists(klass.__module__, resource_path):
                return klass

    def has_access(self, user, topic):
        """Return True if ``user`` can send email to ``topic``.
        Default is False.

        :param user: :class:`allura.model.User` instance
        :param topic: str
        :rtype: bool

        """
        return False

    def is_visible_to(self, user):
        """Return True if ``user`` can view this app.

        :type user: :class:`allura.model.User` instance
        :rtype: bool

        """
        return has_access(self, 'read')(user=user)

    def subscribe_admins(self):
        """Subscribe all project Admins (for this Application's project) to the
        :class:`allura.model.notification.Mailbox` for this Application.

        """
        for uid in g.credentials.userids_with_named_role(self.project._id, 'Admin'):
            model.Mailbox.subscribe(
                type='direct',
                user_id=uid,
                project_id=self.project._id,
                app_config_id=self.config._id)

    def subscribe(self, user):
        """Subscribe :class:`user <allura.model.auth.User>` to the
        :class:`allura.model.notification.Mailbox` for this Application.

        """
        if user and user != model.User.anonymous():
            model.Mailbox.subscribe(
                type='direct',
                user_id=user._id,
                project_id=self.project._id,
                app_config_id=self.config._id)

    @classmethod
    def default_options(cls):
        """Return a ``(name, default value)`` mapping of this Application's
        :class:`config_options <ConfigOption>`.

        :rtype: dict

        """
        return dict(
            (co.name, co.default)
            for co in cls.config_options)

    @classmethod
    def options_on_install(cls):
        """
        Return a list of :class:`config_options <ConfigOption>` which should be
        configured by user during app installation.

        :rtype: list
        """
        return [o for o in cls.config_options
                if o.name in cls.config_on_install]

    def install(self, project):
        'Whatever logic is required to initially set up a tool'
        # Create the discussion object
        discussion = self.DiscussionClass(
            shortname=self.config.options.mount_point,
            name='%s Discussion' % self.config.options.mount_point,
            description='Forum for %s comments' % self.config.options.mount_point)
        session(discussion).flush()
        self.config.discussion_id = discussion._id
        self.subscribe_admins()

    def uninstall(self, project=None, project_id=None):
        'Whatever logic is required to tear down a tool'
        if project_id is None:
            project_id = project._id
        # De-index all the artifacts belonging to this tool in one fell swoop
        index_tasks.solr_del_tool.post(project_id, self.config.options['mount_point'])
        
        for d in model.Discussion.query.find({
                'project_id': project_id,
                'app_config_id': self.config._id}):
            d.delete()
        self.config.delete()
        session(self.config).flush()

    @property
    def uninstallable(self):
        """Return True if this app can be uninstalled. Controls whether the
        'Delete' option appears on the admin menu for this app.

        By default, an app can be uninstalled iff it can be installed, although
        some apps may want/need to override this (e.g. an app which can
        not be installed directly by a user, but may be uninstalled).

        """
        return self.installable

    def main_menu(self):
        """Return a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
        to display in the main project nav for this Application.

        Default implementation returns :attr:`sitemap` without any children.

        """
        sitemap_without_children = []
        for sm in self.sitemap:
            sm_copy = copy(sm)
            sm_copy.children = []
            sitemap_without_children.append(sm_copy)
        return sitemap_without_children

    def sidebar_menu(self):
        """Return a list of :class:`SitemapEntries <allura.app.SitemapEntry>`
        to render in the left sidebar for this Application.

        """
        return []

    def sidebar_menu_js(self):
        """Return Javascript needed by the sidebar menu of this Application.

        :return: a string of Javascript code

        """
        return ""

    @LazyProperty
    def _webhooks(self):
        """A list of webhooks that can be triggered by this app.

        :return: a list of :class:`WebhookSender <allura.webhooks.WebhookSender>`
        """
        tool_name = self.config.tool_name.lower()
        webhooks = [w for w in g.entry_points['webhooks'].itervalues()
                    if tool_name in w.triggered_by]
        return webhooks

    def admin_menu(self, force_options=False):
        """Return the admin menu for this Application.

        Default implementation will return a menu with up to 4 links:

            - 'Permissions', if the current user has admin access to the
                project in which this Application is installed
            - 'Options', if this Application has custom options, or
                ``force_options`` is True
            - 'Rename', for editing this Application's label
            - 'Webhooks', if this Application can trigger any webhooks

        Subclasses should override this method to provide additional admin
        menu items.

        :param force_options: always include an 'Options' link in the menu,
            even if this Application has no custom options
        :return: a list of :class:`SitemapEntries <allura.app.SitemapEntry>`

        """
        admin_url = c.project.url() + 'admin/' + \
            self.config.options.mount_point + '/'
        links = []
        if self.permissions and has_access(c.project, 'admin')():
            links.append(
                SitemapEntry('Permissions', admin_url + 'permissions'))
        if force_options or len(self.config_options) > 3:
            links.append(
                SitemapEntry('Options', admin_url + 'options', className='admin_modal'))
        links.append(
            SitemapEntry('Rename', admin_url + 'edit_label', className='admin_modal'))
        if len(self._webhooks) > 0:
            links.append(SitemapEntry('Webhooks', admin_url + 'webhooks'))
        return links

    @LazyProperty
    def admin_menu_collapse_button(self):
        """Returns button for showing/hiding admin sidebar menu"""
        return SitemapEntry(
            label=u'Admin - {}'.format(self.config.options.mount_label),
            extra_html_attrs={
                'id': 'sidebar-admin-menu-trigger',
            })

    @LazyProperty
    def admin_menu_delete_button(self):
        """Returns button for deleting an app if app can be deleted"""
        anchored_tools = self.project.neighborhood.get_anchored_tools()
        anchored = self.tool_label.lower() in anchored_tools.keys()
        if self.uninstallable and not anchored:
            return SitemapEntry(
                label='Delete',
                url=self.admin_url + 'delete',
                className='admin_modal',
            )

    def handle_message(self, topic, message):
        """Handle incoming email msgs addressed to this tool.
        Default is a no-op.

        :param topic: portion of destination email address preceeding the '@'
        :type topic: str
        :param message: parsed email message
        :type message: dict - result of
            :func:`allura.lib.mail_util.parse_message`
        :rtype: None

        """
        pass

    def handle_artifact_message(self, artifact, message):
        """Handle message addressed to this Application.

        :param artifact: Specific artifact to which the message is addressed
        :type artifact: :class:`allura.model.artifact.Artifact`
        :param message: the message
        :type message: :class:`allura.model.artifact.Message`

        Default implementation posts the message to the appropriate discussion
        thread for the artifact.

        """
        # Find ancestor comment and thread
        thd, parent_id = artifact.get_discussion_thread(message)
        # Handle attachments
        message_id = message['message_id']
        if message.get('filename'):
            # Special case - the actual post may not have been created yet
            log.info('Saving attachment %s', message['filename'])
            fp = StringIO(message['payload'])
            self.AttachmentClass.save_attachment(
                message['filename'], fp,
                content_type=message.get(
                    'content_type', 'application/octet-stream'),
                discussion_id=thd.discussion_id,
                thread_id=thd._id,
                post_id=message_id,
                artifact_id=message_id)
            return
        # Handle duplicates
        post = self.PostClass.query.get(_id=message_id)
        if post:
            log.info(
                'Existing message_id %s found - saving this as text attachment' %
                message_id)
            fp = StringIO(message['payload'])
            post.attach(
                'alternate', fp,
                content_type=message.get(
                    'content_type', 'application/octet-stream'),
                discussion_id=thd.discussion_id,
                thread_id=thd._id,
                post_id=message_id)
        else:
            text = message['payload'] or '--no text body--'
            post = thd.post(
                message_id=message_id,
                parent_id=parent_id,
                text=text,
                subject=message['headers'].get('Subject', 'no subject'))

    def bulk_export(self, f, export_path='', with_attachments=False):
        """Export all artifacts in the tool into json file.

        :param f: File Object to write to

        Set exportable to True for applications implementing this.
        """
        raise NotImplementedError, 'bulk_export'

    def doap(self, parent):
        """App's representation for DOAP API.

        :param parent: Element to contain the results
        :type parent: xml.etree.ElementTree.Element or xml.etree.ElementTree.SubElement
        """
        feature = ET.SubElement(parent, 'sf:feature')
        feature = ET.SubElement(feature, 'sf:Feature')
        ET.SubElement(feature, 'name').text = self.config.options.mount_label
        ET.SubElement(feature, 'foaf:page', {'rdf:resource': h.absurl(self.url)})

    def __json__(self):
        """App's representation for JSON API.

        Returns dict that will be included in project's API under tools key.
        """
        return {
            'name': self.config.tool_name,
            'mount_point': self.config.options.mount_point,
            'url': self.config.url(),
            'icons': self.icons,
            'installable': self.installable,
            'tool_label': self.tool_label,
            'mount_label': self.config.options.mount_label
        }

    def get_attachment_export_path(self, path='', *args):
        return os.path.join(path, self.config.options.mount_point, *args)

    def make_dir_for_attachments(self, path):
        if not os.path.exists(path):
                os.makedirs(path)

    def save_attachments(self, path, attachments):
        self.make_dir_for_attachments(path)
        for attachment in attachments:
            attachment_path = os.path.join(
                path,
                os.path.basename(attachment.filename)
            )
            with open(attachment_path, 'w') as fl:
                fl.write(attachment.rfile().read())


class AdminControllerMixin(object):
    """Provides common functionality admin controllers need"""
    def _before(self, *remainder, **params):
        # Display app's sidebar on admin page, instead of :class:`AdminApp`'s
        c.app = self.app


class DefaultAdminController(BaseController, AdminControllerMixin):

    """Provides basic admin functionality for an :class:`Application`.

    To add more admin functionality for your Application, extend this
    class and then assign an instance of it to the ``admin`` attr of
    your Application::

        class MyApp(Application):
            def __init__(self, *args):
                super(MyApp, self).__init__(*args)
                self.admin = MyAdminController(self)

    """

    def __init__(self, app):
        """Instantiate this controller for an :class:`app <Application>`.

        """
        super(DefaultAdminController, self).__init__()
        self.app = app
        self.webhooks = WebhooksLookup(app)

    @expose()
    def index(self, **kw):
        """Home page for this controller.

        Redirects to the 'permissions' page by default.

        """
        permanent_redirect('permissions')

    @expose('json:')
    @require_post()
    def block_user(self, username, perm, reason=None, **kw):
        if not username or not perm:
            return dict(error='Enter username')
        user = model.User.by_username(username)
        if not user:
            return dict(error='User "%s" not found' % username)
        ace = model.ACE.deny(
            model.ProjectRole.by_user(user, upsert=True)._id, perm, reason)
        if not model.ACL.contains(ace, self.app.acl):
            self.app.acl.append(ace)
            return dict(user_id=str(user._id), username=user.username, reason=reason)
        return dict(error='User "%s" already blocked' % user.username)

    @validate(dict(user_id=V.Set(),
                   perm=V.UnicodeString()))
    @expose('json:')
    @require_post()
    def unblock_user(self, user_id=None, perm=None, **kw):
        try:
            user_id = map(ObjectId, user_id)
        except InvalidId:
            user_id = []
        users = model.User.query.find({'_id': {'$in': user_id}}).all()
        if not users:
            return dict(error='Select user to unblock')
        unblocked = []
        for user in users:
            ace = model.ACE.deny(model.ProjectRole.by_user(user)._id, perm)
            ace = model.ACL.contains(ace, self.app.acl)
            if ace:
                self.app.acl.remove(ace)
                unblocked.append(str(user._id))
        return dict(unblocked=unblocked)

    @expose('jinja:allura:templates/app_admin_permissions.html')
    @without_trailing_slash
    def permissions(self):
        """Render the permissions management web page.

        """
        from ext.admin.widgets import PermissionCard, BlockUser, BlockList
        c.card = PermissionCard()
        c.block_user = BlockUser()
        c.block_list = BlockList()
        permissions = dict((p, []) for p in self.app.permissions)
        block_list = defaultdict(list)
        for ace in self.app.config.acl:
            if ace.access == model.ACE.ALLOW:
                try:
                    permissions[ace.permission].append(ace.role_id)
                except KeyError:
                    # old, unknown permission
                    pass
            elif ace.access == model.ACE.DENY:
                role = model.ProjectRole.query.get(_id=ace.role_id)
                if role.name is None and role.user:
                    block_list[ace.permission].append((role.user, ace.reason))
        return dict(
            app=self.app,
            allow_config=has_access(c.project, 'admin')(),
            permissions=permissions,
            block_list=block_list)

    @expose('jinja:allura:templates/app_admin_edit_label.html')
    def edit_label(self):
        """Renders form to update the Application's ``mount_label``.

        """
        return dict(
            app=self.app,
            allow_config=has_access(self.app, 'configure')())

    @expose()
    @require_post()
    def update_label(self, mount_label):
        """Handles POST to update the Application's ``mount_label``.

        """
        require_access(self.app, 'configure')
        self.app.config.options['mount_label'] = mount_label
        g.post_event('project_menu_updated')
        redirect(request.referer)

    @expose('jinja:allura:templates/app_admin_options.html')
    def options(self):
        """Renders form to update the Application's ``config.options``.

        """
        return dict(
            app=self.app,
            allow_config=has_access(self.app, 'configure')())

    @expose('jinja:allura:templates/app_admin_delete.html')
    def delete(self):
        return dict(app=self.app)

    @expose()
    @require_post()
    def configure(self, **kw):
        """Handle POST to delete the Application or update its
        ``config.options``.

        """
        with h.push_config(c, app=self.app):
            require_access(self.app, 'configure')
            is_admin = self.app.config.tool_name == 'admin'
            if kw.pop('delete', False):
                if is_admin:
                    flash('Cannot delete the admin tool, sorry....')
                    redirect('.')
                c.project.uninstall_app(self.app.config.options.mount_point)
                redirect('..')
            for opt in self.app.config_options:
                if opt in Application.config_options:
                    # skip base options (mount_point, mount_label, ordinal)
                    continue
                val = kw.get(opt.name, '')
                if opt.ming_type == bool:
                    val = asbool(val or False)
                elif opt.ming_type == int:
                    val = asint(val or 0)
                try:
                    val = opt.validate(val)
                except fev.Invalid as e:
                    flash(u'{}: {}'.format(opt.name, str(e)), 'error')
                    continue
                self.app.config.options[opt.name] = val
            if is_admin:
                # possibly moving admin mount point
                redirect('/'
                         + c.project._id
                         + self.app.config.options.mount_point
                         + '/'
                         + self.app.config.options.mount_point
                         + '/')
            else:
                redirect(request.referer)

    @without_trailing_slash
    @expose()
    @h.vardec
    @require_post()
    def update(self, card=None, **kw):
        """Handle POST to update permissions for the Application.

        """
        old_acl = self.app.config.acl
        self.app.config.acl = []
        for args in card:
            perm = args['id']
            new_group_ids = args.get('new', [])
            del_group_ids = []
            group_ids = args.get('value', [])
            if isinstance(new_group_ids, basestring):
                new_group_ids = [new_group_ids]
            if isinstance(group_ids, basestring):
                group_ids = [group_ids]

            for acl in old_acl:
                if (acl['permission'] == perm) and (str(acl['role_id']) not in group_ids) and acl['access'] != model.ACE.DENY:
                    del_group_ids.append(str(acl['role_id']))

            get_role = lambda _id: model.ProjectRole.query.get(_id=ObjectId(_id))
            groups = map(get_role, group_ids)
            new_groups = map(get_role, new_group_ids)
            del_groups = map(get_role, del_group_ids)

            if new_groups or del_groups:
                model.AuditLog.log('updated "%s" permission: "%s" => "%s" for %s' % (
                    perm,
                    ', '.join(map(lambda role: role.name, filter(None, groups + del_groups))),
                    ', '.join(map(lambda role: role.name, filter(None, groups + new_groups))),
                    self.app.config.options['mount_point']))

            role_ids = map(ObjectId, group_ids + new_group_ids)
            self.app.config.acl += [
                model.ACE.allow(r, perm) for r in role_ids]

            # Add all ACEs for user roles back
            for ace in old_acl:
                if (ace.permission == perm) and (ace.access == model.ACE.DENY):
                    self.app.config.acl.append(ace)
        redirect(request.referer)


class WebhooksLookup(BaseController, AdminControllerMixin):

    def __init__(self, app):
        super(WebhooksLookup, self).__init__()
        self.app = app

    @without_trailing_slash
    @expose('jinja:allura:templates/app_admin_webhooks_list.html')
    def index(self):
        webhooks = self.app._webhooks
        if len(webhooks) == 0:
            raise exc.HTTPNotFound()
        configured_hooks = {}
        for hook in webhooks:
            configured_hooks[hook.type] = M.Webhook.query.find({
                'type': hook.type,
                'app_config_id': self.app.config._id}
            ).all()
        return {'webhooks': webhooks,
                'configured_hooks': configured_hooks,
                'admin_url': self.app.admin_url + 'webhooks'}

    @expose()
    def _lookup(self, name, *remainder):
        for hook in self.app._webhooks:
            if hook.type == name and hook.controller:
                return hook.controller(hook, self.app), remainder
        raise exc.HTTPNotFound, name
