~launchpad-pqm/launchpad/devel

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Copyright 2010 Canonical Ltd.  This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).

__metaclass__ = type
__all__ = [
    'NameBlacklistAddView',
    'NameBlacklistEditView',
    'NameBlacklistNavigationMenu',
    'NameBlacklistSetNavigationMenu',
    'NameBlacklistSetView',
    ]

import re

from zope.app.form.browser import TextWidget
from zope.component import (
    adapter,
    getUtility,
    )
from zope.interface import implements

from lp.app.browser.launchpadform import (
    custom_widget,
    LaunchpadFormView,
    )
from lp.registry.browser import RegistryEditFormView
from lp.registry.interfaces.nameblacklist import (
    INameBlacklist,
    INameBlacklistSet,
    )
from lp.services.webapp import action
from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.interfaces import IBreadcrumb
from lp.services.webapp.menu import (
    ApplicationMenu,
    enabled_with_permission,
    Link,
    NavigationMenu,
    )
from lp.services.webapp.publisher import (
    canonical_url,
    LaunchpadView,
    Navigation,
    )


class NameBlacklistValidationMixin:
    """Validate regular expression when adding or editing."""

    def validate(self, data):
        """Validate regular expression."""
        regexp = data['regexp']
        try:
            re.compile(regexp)
            name_blacklist_set = getUtility(INameBlacklistSet)
            if (INameBlacklistSet.providedBy(self.context)
                or self.context.regexp != regexp):
                # Check if the regular expression already exists if a
                # new expression is being created or if an existing
                # regular expression has been modified.
                if name_blacklist_set.getByRegExp(regexp) is not None:
                    self.setFieldError(
                        'regexp',
                        'This regular expression already exists.')
        except re.error, e:
            self.setFieldError(
                'regexp',
                'Invalid regular expression: %s' % e)


class NameBlacklistEditView(NameBlacklistValidationMixin,
                            RegistryEditFormView):
    """View for editing a blacklist expression."""

    schema = INameBlacklist
    field_names = ['regexp', 'admin', 'comment']
    label = "Edit a blacklist expression"
    page_title = label

    @property
    def cancel_url(self):
        return canonical_url(getUtility(INameBlacklistSet))

    next_url = cancel_url


class NameBlacklistAddView(NameBlacklistValidationMixin, LaunchpadFormView):
    """View for adding a blacklist expression."""

    schema = INameBlacklist
    field_names = ['regexp', 'admin', 'comment']
    label = "Add a new blacklist expression"
    page_title = label

    custom_widget('regexp', TextWidget, displayWidth=60)

    @property
    def cancel_url(self):
        """See `LaunchpadFormView`."""
        return canonical_url(self.context)

    next_url = cancel_url

    @action("Add to blacklist", name='add')
    def add_action(self, action, data):
        name_blacklist_set = getUtility(INameBlacklistSet)
        name_blacklist_set.create(
            regexp=data['regexp'],
            comment=data['comment'],
            admin=data['admin'],
            )
        self.request.response.addInfoNotification(
            'Regular expression "%s" has been added to the name blacklist.'
            % data['regexp'])


class NameBlacklistSetView(LaunchpadView):
    """View for /+nameblacklists top level collection."""

    label = (
        'Blacklist for names of Launchpad pillars and persons')
    page_title = label


class NameBlacklistSetNavigation(Navigation):

    usedfor = INameBlacklistSet

    def traverse(self, name):
        return self.context.get(name)


class NameBlacklistSetNavigationMenu(NavigationMenu):
    """Action menu for NameBlacklistSet."""
    usedfor = INameBlacklistSet
    facet = 'overview'
    links = [
        'add_blacklist_expression',
        ]

    @enabled_with_permission('launchpad.Edit')
    def add_blacklist_expression(self):
        return Link('+add', 'Add blacklist expression', icon='add')


class NameBlacklistNavigationMenu(ApplicationMenu):
    """Action menu for NameBlacklist."""
    usedfor = INameBlacklist
    facet = 'overview'
    links = [
        'edit_blacklist_expression',
        ]

    @enabled_with_permission('launchpad.Edit')
    def edit_blacklist_expression(self):
        return Link('+edit', 'Edit blacklist expression', icon='edit')


@adapter(INameBlacklistSet)
class NameBlacklistSetBreadcrumb(Breadcrumb):
    """Return a breadcrumb for an `INameBlackListSet`."""

    implements(IBreadcrumb)

    text = "Name Blacklist"