We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Enable project resource pages (across all languages) for disabled projects for admins
The change in #3997 allowed admins to browse through disabled projects but project resource pages are still unavailable.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pootle/core/decorators.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 #
4 # Copyright (C) Pootle contributors.
5 #
6 # This file is a part of the Pootle project. It is distributed under the GPL3
7 # or later license. See the LICENSE file for a copy of the license and the
8 # AUTHORS file for copyright and authorship information.
9 
10 from functools import wraps
11 
12 from django.contrib.auth import get_user_model
13 from django.core.exceptions import PermissionDenied
14 from django.core.urlresolvers import reverse
15 from django.db import connection
16 from django.http import Http404
17 from django.shortcuts import get_object_or_404, redirect
18 from django.utils.translation import ugettext as _
19 
20 from pootle_app.models.directory import Directory
21 from pootle_app.models.permissions import (check_permission,
22                                            get_matching_permissions)
23 from pootle_language.models import Language
24 from pootle_project.models import Project, ProjectSet, ProjectResource
25 from pootle_store.models import Store
26 from pootle_translationproject.models import TranslationProject
27 from virtualfolder.helpers import extract_vfolder_from_path
28 
29 from .exceptions import Http400
30 from .url_helpers import split_pootle_path
31 
32 
33 CLS2ATTR = {
34     'TranslationProject': 'translation_project',
35     'Project': 'project',
36     'Language': 'language',
37 }
38 
39 
40 def get_path_obj(func):
41     @wraps(func)
42     def wrapped(request, *args, **kwargs):
43         if request.is_ajax():
44             pootle_path = request.GET.get('path', None)
45             if pootle_path is None:
46                 raise Http400(_('Arguments missing.'))
47 
48             language_code, project_code, dir_path, filename = \
49                 split_pootle_path(pootle_path)
50             kwargs['dir_path'] = dir_path
51             kwargs['filename'] = filename
52 
53             # Remove potentially present but unwanted args
54             try:
55                 del kwargs['language_code']
56                 del kwargs['project_code']
57             except KeyError:
58                 pass
59         else:
60             language_code = kwargs.pop('language_code', None)
61             project_code = kwargs.pop('project_code', None)
62 
63         if language_code and project_code:
64             try:
65                 path_obj = TranslationProject.objects.get_for_user(
66                     user=request.user,
67                     language_code=language_code,
68                     project_code=project_code,
69                 )
70             except TranslationProject.DoesNotExist:
71                 path_obj = None
72 
73             if path_obj is None:
74                 if not request.is_ajax():
75                     # Explicit selection via the UI: redirect either to
76                     # ``/language_code/`` or ``/projects/project_code/``
77                     user_choice = request.COOKIES.get('user-choice', None)
78                     if user_choice and user_choice in ('language', 'project',):
79                         url = {
80                             'language': reverse('pootle-language-browse',
81                                                 args=[language_code]),
82                             'project': reverse('pootle-project-browse',
83                                                args=[project_code, '', '']),
84                         }
85                         response = redirect(url[user_choice])
86                         response.delete_cookie('user-choice')
87 
88                         return response
89 
90                 raise Http404
91         elif language_code:
92             user_projects = Project.accessible_by_user(request.user)
93             language = get_object_or_404(Language, code=language_code)
94             children = language.children \
95                                .filter(project__code__in=user_projects)
96             language.set_children(children)
97             path_obj = language
98         elif project_code:
99             try:
100                 path_obj = Project.objects.get_for_user(project_code,
101                                                         request.user)
102             except Project.DoesNotExist:
103                 raise Http404
104         else:  # No arguments: all user-accessible projects
105             user_projects = Project.accessible_by_user(request.user)
106             user_projects = Project.objects.for_user(request.user) \
107                                            .filter(code__in=user_projects)
108 
109             path_obj = ProjectSet(user_projects)
110 
111         request.ctx_obj = path_obj
112         request.ctx_path = path_obj.pootle_path
113         request.resource_obj = path_obj
114         request.pootle_path = path_obj.pootle_path
115 
116         return func(request, path_obj, *args, **kwargs)
117 
118     return wrapped
119 
120 
121 def set_resource(request, path_obj, dir_path, filename):
122     """Loads :cls:`pootle_app.models.Directory` and
123     :cls:`pootle_store.models.Store` models and populates the
124     request object.
125 
126     :param path_obj: A path-like object object.
127     :param dir_path: Path relative to the root of `path_obj`.
128     :param filename: Optional filename.
129     """
130     obj_directory = getattr(path_obj, 'directory', path_obj)
131     ctx_path = obj_directory.pootle_path
132     resource_path = dir_path
133     pootle_path = ctx_path + dir_path
134 
135     directory = None
136     store = None
137 
138     is_404 = False
139 
140     # Get a clean pootle path for retrieving the directory or store.
141     # A clean pootle path is a pootle path without any virtual folder name on
142     # it. For example /af/test_vfolders/browser/chrome/ is the corresponding
143     # clean pootle path for /af/test_vfolders/browser/vfolder8/chrome/
144     vfolder, clean_pootle_path = extract_vfolder_from_path(pootle_path)
145 
146     if filename:
147         pootle_path = pootle_path + filename
148         clean_pootle_path = clean_pootle_path + filename
149         resource_path = resource_path + filename
150 
151         try:
152             store = Store.objects.live().select_related(
153                 'translation_project',
154                 'parent',
155             ).get(pootle_path=clean_pootle_path)
156             directory = store.parent
157         except Store.DoesNotExist:
158             is_404 = True
159 
160     if directory is None and not is_404:
161         if dir_path:
162             try:
163                 directory = Directory.objects.live().get(pootle_path=clean_pootle_path)
164             except Directory.DoesNotExist:
165                 is_404 = True
166         else:
167             directory = obj_directory
168 
169     if is_404:  # Try parent directory
170         language_code, project_code, dp, fn = split_pootle_path(clean_pootle_path)
171         if not filename:
172             dir_path = dir_path[:dir_path[:-1].rfind('/') + 1]
173 
174         url = reverse('pootle-tp-browse',
175                       args=[language_code, project_code, dir_path])
176         request.redirect_url = url
177 
178         raise Http404
179 
180     request.store = store
181     request.directory = directory
182     request.pootle_path = pootle_path
183     request.current_vfolder = getattr(vfolder, 'pk', '')
184 
185     request.resource_obj = store or (directory if dir_path else path_obj)
186     request.resource_path = resource_path
187     request.ctx_obj = path_obj or request.resource_obj
188     request.ctx_path = ctx_path
189 
190 
191 def set_project_resource(request, path_obj, dir_path, filename):
192     """Loads :cls:`pootle_app.models.Directory` and
193     :cls:`pootle_store.models.Store` models and populates the
194     request object.
195 
196     This is the same as `set_resource` but operates at the project level
197     across all languages.
198 
199     :param path_obj: A :cls:`pootle_project.models.Project` object.
200     :param dir_path: Path relative to the root of `path_obj`.
201     :param filename: Optional filename.
202     """
203     query_ctx_path = ''.join(['/%/', path_obj.code, '/'])
204     query_pootle_path = query_ctx_path + dir_path
205 
206     obj_directory = getattr(path_obj, 'directory', path_obj)
207     ctx_path = obj_directory.pootle_path
208     resource_path = dir_path
209     pootle_path = ctx_path + dir_path
210 
211     # List of disabled TP paths
212     disabled_tps = TranslationProject.objects.disabled().filter(
213         project__code=path_obj.code,
214     ).values_list('pootle_path', flat=True)
215     disabled_tps = list(disabled_tps)
216     disabled_tps.append('/templates/')
217     disabled_tps_regex = '^%s' % u'|'.join(disabled_tps)
218     sql_not_regex = 'NOT REGEXP'
219     if connection.vendor == 'postgresql':
220         sql_not_regex = '!~'
221 
222     if filename:
223         query_pootle_path = query_pootle_path + filename
224         pootle_path = pootle_path + filename
225         resource_path = resource_path + filename
226 
227         resources = Store.objects.live().extra(
228             where=[
229                 'pootle_store_store.pootle_path LIKE %s',
230                 'pootle_store_store.pootle_path ' + sql_not_regex + ' %s',
231             ], params=[query_pootle_path, disabled_tps_regex]
232         ).select_related('translation_project__language')
233     else:
234         resources = Directory.objects.live().extra(
235             where=[
236                 'pootle_app_directory.pootle_path LIKE %s',
237                 'pootle_app_directory.pootle_path ' + sql_not_regex + ' %s',
238             ], params=[query_pootle_path, disabled_tps_regex]
239         ).select_related('parent')
240 
241     if not resources.exists():
242         raise Http404
243 
244     request.store = None
245     request.directory = None
246     request.pootle_path = pootle_path
247 
248     request.resource_obj = ProjectResource(resources, pootle_path)
249     request.resource_path = resource_path
250     request.ctx_obj = path_obj or request.resource_obj
251     request.ctx_path = ctx_path
252 
253 
254 def get_resource(func):
255     @wraps(func)
256     def wrapped(request, path_obj, dir_path, filename):
257         """Gets resources associated to the current context."""
258         try:
259             directory = getattr(path_obj, 'directory', path_obj)
260             if directory.is_project() and (dir_path or filename):
261                 set_project_resource(request, path_obj, dir_path, filename)
262             else:
263                 set_resource(request, path_obj, dir_path, filename)
264         except Http404:
265             if not request.is_ajax():
266                 user_choice = request.COOKIES.get('user-choice', None)
267                 url = None
268 
269                 if hasattr(request, 'redirect_url'):
270                     url = request.redirect_url
271                 elif user_choice in ('language', 'resource',):
272                     project = (path_obj if isinstance(path_obj, Project)
273                                         else path_obj.project)
274                     url = reverse('pootle-project-browse',
275                                   args=[project.code, dir_path, filename])
276 
277                 if url is not None:
278                     response = redirect(url)
279 
280                     if user_choice in ('language', 'resource',):
281                         # XXX: should we rather delete this in a single place?
282                         response.delete_cookie('user-choice')
283 
284                     return response
285 
286             raise Http404
287 
288         return func(request, path_obj, dir_path, filename)
289 
290     return wrapped
291 
292 
293 def permission_required(permission_code):
294     """Checks for `permission_code` in the current context.
295 
296     To retrieve the proper context, the `get_path_obj` decorator must be
297     used along with this decorator.
298     """
299     def wrapped(func):
300         @wraps(func)
301         def _wrapped(request, *args, **kwargs):
302             path_obj = args[0]
303             directory = getattr(path_obj, 'directory', path_obj)
304 
305             # HACKISH: some old code relies on
306             # `request.translation_project`, `request.language` etc.
307             # being set, so we need to set that too.
308             attr_name = CLS2ATTR.get(path_obj.__class__.__name__,
309                                      'path_obj')
310             setattr(request, attr_name, path_obj)
311 
312             User = get_user_model()
313             request.profile = User.get(request.user)
314             request.permissions = get_matching_permissions(request.profile,
315                                                            directory)
316 
317             if not permission_code:
318                 return func(request, *args, **kwargs)
319 
320             if not check_permission(permission_code, request):
321                 raise PermissionDenied(
322                     _("Insufficient rights to access this page."),
323                 )
324 
325             return func(request, *args, **kwargs)
326         return _wrapped
327     return wrapped
328 
329 
330 def admin_required(func):
331     @wraps(func)
332     def wrapped(request, *args, **kwargs):
333         if not request.user.is_superuser:
334             raise PermissionDenied(
335                 _("You do not have rights to administer Pootle.")
336             )
337         return func(request, *args, **kwargs)
338 
339     return wrapped
340
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pootle/core/decorators.py b/pootle/core/decorators.py
--- a/pootle/core/decorators.py
+++ b/pootle/core/decorators.py
@@ -208,16 +208,17 @@
     resource_path = dir_path
     pootle_path = ctx_path + dir_path
 
-    # List of disabled TP paths
-    disabled_tps = TranslationProject.objects.disabled().filter(
+    # List of TP paths available for user
+    user_tps = TranslationProject.objects.for_user(request.user)
+    user_tps = user_tps.filter(
         project__code=path_obj.code,
     ).values_list('pootle_path', flat=True)
-    disabled_tps = list(disabled_tps)
-    disabled_tps.append('/templates/')
-    disabled_tps_regex = '^%s' % u'|'.join(disabled_tps)
-    sql_not_regex = 'NOT REGEXP'
+    user_tps = list(path for path in user_tps
+                    if not path.startswith('/templates/'))
+    user_tps_regex = '^%s' % u'|'.join(user_tps)
+    sql_regex = 'REGEXP'
     if connection.vendor == 'postgresql':
-        sql_not_regex = '!~'
+        sql_regex = '~'
 
     if filename:
         query_pootle_path = query_pootle_path + filename
@@ -227,15 +228,15 @@
         resources = Store.objects.live().extra(
             where=[
                 'pootle_store_store.pootle_path LIKE %s',
-                'pootle_store_store.pootle_path ' + sql_not_regex + ' %s',
-            ], params=[query_pootle_path, disabled_tps_regex]
+                'pootle_store_store.pootle_path ' + sql_regex + ' %s',
+            ], params=[query_pootle_path, user_tps_regex]
         ).select_related('translation_project__language')
     else:
         resources = Directory.objects.live().extra(
             where=[
                 'pootle_app_directory.pootle_path LIKE %s',
-                'pootle_app_directory.pootle_path ' + sql_not_regex + ' %s',
-            ], params=[query_pootle_path, disabled_tps_regex]
+                'pootle_app_directory.pootle_path ' + sql_regex + ' %s',
+            ], params=[query_pootle_path, user_tps_regex]
         ).select_related('parent')
 
     if not resources.exists():

{"golden_diff": "diff --git a/pootle/core/decorators.py b/pootle/core/decorators.py\n--- a/pootle/core/decorators.py\n+++ b/pootle/core/decorators.py\n@@ -208,16 +208,17 @@\n     resource_path = dir_path\n     pootle_path = ctx_path + dir_path\n \n-    # List of disabled TP paths\n-    disabled_tps = TranslationProject.objects.disabled().filter(\n+    # List of TP paths available for user\n+    user_tps = TranslationProject.objects.for_user(request.user)\n+    user_tps = user_tps.filter(\n         project__code=path_obj.code,\n     ).values_list('pootle_path', flat=True)\n-    disabled_tps = list(disabled_tps)\n-    disabled_tps.append('/templates/')\n-    disabled_tps_regex = '^%s' % u'|'.join(disabled_tps)\n-    sql_not_regex = 'NOT REGEXP'\n+    user_tps = list(path for path in user_tps\n+                    if not path.startswith('/templates/'))\n+    user_tps_regex = '^%s' % u'|'.join(user_tps)\n+    sql_regex = 'REGEXP'\n     if connection.vendor == 'postgresql':\n-        sql_not_regex = '!~'\n+        sql_regex = '~'\n \n     if filename:\n         query_pootle_path = query_pootle_path + filename\n@@ -227,15 +228,15 @@\n         resources = Store.objects.live().extra(\n             where=[\n                 'pootle_store_store.pootle_path LIKE %s',\n-                'pootle_store_store.pootle_path ' + sql_not_regex + ' %s',\n-            ], params=[query_pootle_path, disabled_tps_regex]\n+                'pootle_store_store.pootle_path ' + sql_regex + ' %s',\n+            ], params=[query_pootle_path, user_tps_regex]\n         ).select_related('translation_project__language')\n     else:\n         resources = Directory.objects.live().extra(\n             where=[\n                 'pootle_app_directory.pootle_path LIKE %s',\n-                'pootle_app_directory.pootle_path ' + sql_not_regex + ' %s',\n-            ], params=[query_pootle_path, disabled_tps_regex]\n+                'pootle_app_directory.pootle_path ' + sql_regex + ' %s',\n+            ], params=[query_pootle_path, user_tps_regex]\n         ).select_related('parent')\n \n     if not resources.exists():\n", "issue": "Enable project resource pages (across all languages) for disabled projects for admins\nThe change in #3997 allowed admins to browse through disabled projects but project resource pages are still unavailable.\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright (C) Pootle contributors.\n#\n# This file is a part of the Pootle project. It is distributed under the GPL3\n# or later license. See the LICENSE file for a copy of the license and the\n# AUTHORS file for copyright and authorship information.\n\nfrom functools import wraps\n\nfrom django.contrib.auth import get_user_model\nfrom django.core.exceptions import PermissionDenied\nfrom django.core.urlresolvers import reverse\nfrom django.db import connection\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils.translation import ugettext as _\n\nfrom pootle_app.models.directory import Directory\nfrom pootle_app.models.permissions import (check_permission,\n                                           get_matching_permissions)\nfrom pootle_language.models import Language\nfrom pootle_project.models import Project, ProjectSet, ProjectResource\nfrom pootle_store.models import Store\nfrom pootle_translationproject.models import TranslationProject\nfrom virtualfolder.helpers import extract_vfolder_from_path\n\nfrom .exceptions import Http400\nfrom .url_helpers import split_pootle_path\n\n\nCLS2ATTR = {\n    'TranslationProject': 'translation_project',\n    'Project': 'project',\n    'Language': 'language',\n}\n\n\ndef get_path_obj(func):\n    @wraps(func)\n    def wrapped(request, *args, **kwargs):\n        if request.is_ajax():\n            pootle_path = request.GET.get('path', None)\n            if pootle_path is None:\n                raise Http400(_('Arguments missing.'))\n\n            language_code, project_code, dir_path, filename = \\\n                split_pootle_path(pootle_path)\n            kwargs['dir_path'] = dir_path\n            kwargs['filename'] = filename\n\n            # Remove potentially present but unwanted args\n            try:\n                del kwargs['language_code']\n                del kwargs['project_code']\n            except KeyError:\n                pass\n        else:\n            language_code = kwargs.pop('language_code', None)\n            project_code = kwargs.pop('project_code', None)\n\n        if language_code and project_code:\n            try:\n                path_obj = TranslationProject.objects.get_for_user(\n                    user=request.user,\n                    language_code=language_code,\n                    project_code=project_code,\n                )\n            except TranslationProject.DoesNotExist:\n                path_obj = None\n\n            if path_obj is None:\n                if not request.is_ajax():\n                    # Explicit selection via the UI: redirect either to\n                    # ``/language_code/`` or ``/projects/project_code/``\n                    user_choice = request.COOKIES.get('user-choice', None)\n                    if user_choice and user_choice in ('language', 'project',):\n                        url = {\n                            'language': reverse('pootle-language-browse',\n                                                args=[language_code]),\n                            'project': reverse('pootle-project-browse',\n                                               args=[project_code, '', '']),\n                        }\n                        response = redirect(url[user_choice])\n                        response.delete_cookie('user-choice')\n\n                        return response\n\n                raise Http404\n        elif language_code:\n            user_projects = Project.accessible_by_user(request.user)\n            language = get_object_or_404(Language, code=language_code)\n            children = language.children \\\n                               .filter(project__code__in=user_projects)\n            language.set_children(children)\n            path_obj = language\n        elif project_code:\n            try:\n                path_obj = Project.objects.get_for_user(project_code,\n                                                        request.user)\n            except Project.DoesNotExist:\n                raise Http404\n        else:  # No arguments: all user-accessible projects\n            user_projects = Project.accessible_by_user(request.user)\n            user_projects = Project.objects.for_user(request.user) \\\n                                           .filter(code__in=user_projects)\n\n            path_obj = ProjectSet(user_projects)\n\n        request.ctx_obj = path_obj\n        request.ctx_path = path_obj.pootle_path\n        request.resource_obj = path_obj\n        request.pootle_path = path_obj.pootle_path\n\n        return func(request, path_obj, *args, **kwargs)\n\n    return wrapped\n\n\ndef set_resource(request, path_obj, dir_path, filename):\n    \"\"\"Loads :cls:`pootle_app.models.Directory` and\n    :cls:`pootle_store.models.Store` models and populates the\n    request object.\n\n    :param path_obj: A path-like object object.\n    :param dir_path: Path relative to the root of `path_obj`.\n    :param filename: Optional filename.\n    \"\"\"\n    obj_directory = getattr(path_obj, 'directory', path_obj)\n    ctx_path = obj_directory.pootle_path\n    resource_path = dir_path\n    pootle_path = ctx_path + dir_path\n\n    directory = None\n    store = None\n\n    is_404 = False\n\n    # Get a clean pootle path for retrieving the directory or store.\n    # A clean pootle path is a pootle path without any virtual folder name on\n    # it. For example /af/test_vfolders/browser/chrome/ is the corresponding\n    # clean pootle path for /af/test_vfolders/browser/vfolder8/chrome/\n    vfolder, clean_pootle_path = extract_vfolder_from_path(pootle_path)\n\n    if filename:\n        pootle_path = pootle_path + filename\n        clean_pootle_path = clean_pootle_path + filename\n        resource_path = resource_path + filename\n\n        try:\n            store = Store.objects.live().select_related(\n                'translation_project',\n                'parent',\n            ).get(pootle_path=clean_pootle_path)\n            directory = store.parent\n        except Store.DoesNotExist:\n            is_404 = True\n\n    if directory is None and not is_404:\n        if dir_path:\n            try:\n                directory = Directory.objects.live().get(pootle_path=clean_pootle_path)\n            except Directory.DoesNotExist:\n                is_404 = True\n        else:\n            directory = obj_directory\n\n    if is_404:  # Try parent directory\n        language_code, project_code, dp, fn = split_pootle_path(clean_pootle_path)\n        if not filename:\n            dir_path = dir_path[:dir_path[:-1].rfind('/') + 1]\n\n        url = reverse('pootle-tp-browse',\n                      args=[language_code, project_code, dir_path])\n        request.redirect_url = url\n\n        raise Http404\n\n    request.store = store\n    request.directory = directory\n    request.pootle_path = pootle_path\n    request.current_vfolder = getattr(vfolder, 'pk', '')\n\n    request.resource_obj = store or (directory if dir_path else path_obj)\n    request.resource_path = resource_path\n    request.ctx_obj = path_obj or request.resource_obj\n    request.ctx_path = ctx_path\n\n\ndef set_project_resource(request, path_obj, dir_path, filename):\n    \"\"\"Loads :cls:`pootle_app.models.Directory` and\n    :cls:`pootle_store.models.Store` models and populates the\n    request object.\n\n    This is the same as `set_resource` but operates at the project level\n    across all languages.\n\n    :param path_obj: A :cls:`pootle_project.models.Project` object.\n    :param dir_path: Path relative to the root of `path_obj`.\n    :param filename: Optional filename.\n    \"\"\"\n    query_ctx_path = ''.join(['/%/', path_obj.code, '/'])\n    query_pootle_path = query_ctx_path + dir_path\n\n    obj_directory = getattr(path_obj, 'directory', path_obj)\n    ctx_path = obj_directory.pootle_path\n    resource_path = dir_path\n    pootle_path = ctx_path + dir_path\n\n    # List of disabled TP paths\n    disabled_tps = TranslationProject.objects.disabled().filter(\n        project__code=path_obj.code,\n    ).values_list('pootle_path', flat=True)\n    disabled_tps = list(disabled_tps)\n    disabled_tps.append('/templates/')\n    disabled_tps_regex = '^%s' % u'|'.join(disabled_tps)\n    sql_not_regex = 'NOT REGEXP'\n    if connection.vendor == 'postgresql':\n        sql_not_regex = '!~'\n\n    if filename:\n        query_pootle_path = query_pootle_path + filename\n        pootle_path = pootle_path + filename\n        resource_path = resource_path + filename\n\n        resources = Store.objects.live().extra(\n            where=[\n                'pootle_store_store.pootle_path LIKE %s',\n                'pootle_store_store.pootle_path ' + sql_not_regex + ' %s',\n            ], params=[query_pootle_path, disabled_tps_regex]\n        ).select_related('translation_project__language')\n    else:\n        resources = Directory.objects.live().extra(\n            where=[\n                'pootle_app_directory.pootle_path LIKE %s',\n                'pootle_app_directory.pootle_path ' + sql_not_regex + ' %s',\n            ], params=[query_pootle_path, disabled_tps_regex]\n        ).select_related('parent')\n\n    if not resources.exists():\n        raise Http404\n\n    request.store = None\n    request.directory = None\n    request.pootle_path = pootle_path\n\n    request.resource_obj = ProjectResource(resources, pootle_path)\n    request.resource_path = resource_path\n    request.ctx_obj = path_obj or request.resource_obj\n    request.ctx_path = ctx_path\n\n\ndef get_resource(func):\n    @wraps(func)\n    def wrapped(request, path_obj, dir_path, filename):\n        \"\"\"Gets resources associated to the current context.\"\"\"\n        try:\n            directory = getattr(path_obj, 'directory', path_obj)\n            if directory.is_project() and (dir_path or filename):\n                set_project_resource(request, path_obj, dir_path, filename)\n            else:\n                set_resource(request, path_obj, dir_path, filename)\n        except Http404:\n            if not request.is_ajax():\n                user_choice = request.COOKIES.get('user-choice', None)\n                url = None\n\n                if hasattr(request, 'redirect_url'):\n                    url = request.redirect_url\n                elif user_choice in ('language', 'resource',):\n                    project = (path_obj if isinstance(path_obj, Project)\n                                        else path_obj.project)\n                    url = reverse('pootle-project-browse',\n                                  args=[project.code, dir_path, filename])\n\n                if url is not None:\n                    response = redirect(url)\n\n                    if user_choice in ('language', 'resource',):\n                        # XXX: should we rather delete this in a single place?\n                        response.delete_cookie('user-choice')\n\n                    return response\n\n            raise Http404\n\n        return func(request, path_obj, dir_path, filename)\n\n    return wrapped\n\n\ndef permission_required(permission_code):\n    \"\"\"Checks for `permission_code` in the current context.\n\n    To retrieve the proper context, the `get_path_obj` decorator must be\n    used along with this decorator.\n    \"\"\"\n    def wrapped(func):\n        @wraps(func)\n        def _wrapped(request, *args, **kwargs):\n            path_obj = args[0]\n            directory = getattr(path_obj, 'directory', path_obj)\n\n            # HACKISH: some old code relies on\n            # `request.translation_project`, `request.language` etc.\n            # being set, so we need to set that too.\n            attr_name = CLS2ATTR.get(path_obj.__class__.__name__,\n                                     'path_obj')\n            setattr(request, attr_name, path_obj)\n\n            User = get_user_model()\n            request.profile = User.get(request.user)\n            request.permissions = get_matching_permissions(request.profile,\n                                                           directory)\n\n            if not permission_code:\n                return func(request, *args, **kwargs)\n\n            if not check_permission(permission_code, request):\n                raise PermissionDenied(\n                    _(\"Insufficient rights to access this page.\"),\n                )\n\n            return func(request, *args, **kwargs)\n        return _wrapped\n    return wrapped\n\n\ndef admin_required(func):\n    @wraps(func)\n    def wrapped(request, *args, **kwargs):\n        if not request.user.is_superuser:\n            raise PermissionDenied(\n                _(\"You do not have rights to administer Pootle.\")\n            )\n        return func(request, *args, **kwargs)\n\n    return wrapped\n", "path": "pootle/core/decorators.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n#\n# Copyright (C) Pootle contributors.\n#\n# This file is a part of the Pootle project. It is distributed under the GPL3\n# or later license. See the LICENSE file for a copy of the license and the\n# AUTHORS file for copyright and authorship information.\n\nfrom functools import wraps\n\nfrom django.contrib.auth import get_user_model\nfrom django.core.exceptions import PermissionDenied\nfrom django.core.urlresolvers import reverse\nfrom django.db import connection\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils.translation import ugettext as _\n\nfrom pootle_app.models.directory import Directory\nfrom pootle_app.models.permissions import (check_permission,\n                                           get_matching_permissions)\nfrom pootle_language.models import Language\nfrom pootle_project.models import Project, ProjectSet, ProjectResource\nfrom pootle_store.models import Store\nfrom pootle_translationproject.models import TranslationProject\nfrom virtualfolder.helpers import extract_vfolder_from_path\n\nfrom .exceptions import Http400\nfrom .url_helpers import split_pootle_path\n\n\nCLS2ATTR = {\n    'TranslationProject': 'translation_project',\n    'Project': 'project',\n    'Language': 'language',\n}\n\n\ndef get_path_obj(func):\n    @wraps(func)\n    def wrapped(request, *args, **kwargs):\n        if request.is_ajax():\n            pootle_path = request.GET.get('path', None)\n            if pootle_path is None:\n                raise Http400(_('Arguments missing.'))\n\n            language_code, project_code, dir_path, filename = \\\n                split_pootle_path(pootle_path)\n            kwargs['dir_path'] = dir_path\n            kwargs['filename'] = filename\n\n            # Remove potentially present but unwanted args\n            try:\n                del kwargs['language_code']\n                del kwargs['project_code']\n            except KeyError:\n                pass\n        else:\n            language_code = kwargs.pop('language_code', None)\n            project_code = kwargs.pop('project_code', None)\n\n        if language_code and project_code:\n            try:\n                path_obj = TranslationProject.objects.get_for_user(\n                    user=request.user,\n                    language_code=language_code,\n                    project_code=project_code,\n                )\n            except TranslationProject.DoesNotExist:\n                path_obj = None\n\n            if path_obj is None:\n                if not request.is_ajax():\n                    # Explicit selection via the UI: redirect either to\n                    # ``/language_code/`` or ``/projects/project_code/``\n                    user_choice = request.COOKIES.get('user-choice', None)\n                    if user_choice and user_choice in ('language', 'project',):\n                        url = {\n                            'language': reverse('pootle-language-browse',\n                                                args=[language_code]),\n                            'project': reverse('pootle-project-browse',\n                                               args=[project_code, '', '']),\n                        }\n                        response = redirect(url[user_choice])\n                        response.delete_cookie('user-choice')\n\n                        return response\n\n                raise Http404\n        elif language_code:\n            user_projects = Project.accessible_by_user(request.user)\n            language = get_object_or_404(Language, code=language_code)\n            children = language.children \\\n                               .filter(project__code__in=user_projects)\n            language.set_children(children)\n            path_obj = language\n        elif project_code:\n            try:\n                path_obj = Project.objects.get_for_user(project_code,\n                                                        request.user)\n            except Project.DoesNotExist:\n                raise Http404\n        else:  # No arguments: all user-accessible projects\n            user_projects = Project.accessible_by_user(request.user)\n            user_projects = Project.objects.for_user(request.user) \\\n                                           .filter(code__in=user_projects)\n\n            path_obj = ProjectSet(user_projects)\n\n        request.ctx_obj = path_obj\n        request.ctx_path = path_obj.pootle_path\n        request.resource_obj = path_obj\n        request.pootle_path = path_obj.pootle_path\n\n        return func(request, path_obj, *args, **kwargs)\n\n    return wrapped\n\n\ndef set_resource(request, path_obj, dir_path, filename):\n    \"\"\"Loads :cls:`pootle_app.models.Directory` and\n    :cls:`pootle_store.models.Store` models and populates the\n    request object.\n\n    :param path_obj: A path-like object object.\n    :param dir_path: Path relative to the root of `path_obj`.\n    :param filename: Optional filename.\n    \"\"\"\n    obj_directory = getattr(path_obj, 'directory', path_obj)\n    ctx_path = obj_directory.pootle_path\n    resource_path = dir_path\n    pootle_path = ctx_path + dir_path\n\n    directory = None\n    store = None\n\n    is_404 = False\n\n    # Get a clean pootle path for retrieving the directory or store.\n    # A clean pootle path is a pootle path without any virtual folder name on\n    # it. For example /af/test_vfolders/browser/chrome/ is the corresponding\n    # clean pootle path for /af/test_vfolders/browser/vfolder8/chrome/\n    vfolder, clean_pootle_path = extract_vfolder_from_path(pootle_path)\n\n    if filename:\n        pootle_path = pootle_path + filename\n        clean_pootle_path = clean_pootle_path + filename\n        resource_path = resource_path + filename\n\n        try:\n            store = Store.objects.live().select_related(\n                'translation_project',\n                'parent',\n            ).get(pootle_path=clean_pootle_path)\n            directory = store.parent\n        except Store.DoesNotExist:\n            is_404 = True\n\n    if directory is None and not is_404:\n        if dir_path:\n            try:\n                directory = Directory.objects.live().get(pootle_path=clean_pootle_path)\n            except Directory.DoesNotExist:\n                is_404 = True\n        else:\n            directory = obj_directory\n\n    if is_404:  # Try parent directory\n        language_code, project_code, dp, fn = split_pootle_path(clean_pootle_path)\n        if not filename:\n            dir_path = dir_path[:dir_path[:-1].rfind('/') + 1]\n\n        url = reverse('pootle-tp-browse',\n                      args=[language_code, project_code, dir_path])\n        request.redirect_url = url\n\n        raise Http404\n\n    request.store = store\n    request.directory = directory\n    request.pootle_path = pootle_path\n    request.current_vfolder = getattr(vfolder, 'pk', '')\n\n    request.resource_obj = store or (directory if dir_path else path_obj)\n    request.resource_path = resource_path\n    request.ctx_obj = path_obj or request.resource_obj\n    request.ctx_path = ctx_path\n\n\ndef set_project_resource(request, path_obj, dir_path, filename):\n    \"\"\"Loads :cls:`pootle_app.models.Directory` and\n    :cls:`pootle_store.models.Store` models and populates the\n    request object.\n\n    This is the same as `set_resource` but operates at the project level\n    across all languages.\n\n    :param path_obj: A :cls:`pootle_project.models.Project` object.\n    :param dir_path: Path relative to the root of `path_obj`.\n    :param filename: Optional filename.\n    \"\"\"\n    query_ctx_path = ''.join(['/%/', path_obj.code, '/'])\n    query_pootle_path = query_ctx_path + dir_path\n\n    obj_directory = getattr(path_obj, 'directory', path_obj)\n    ctx_path = obj_directory.pootle_path\n    resource_path = dir_path\n    pootle_path = ctx_path + dir_path\n\n    # List of TP paths available for user\n    user_tps = TranslationProject.objects.for_user(request.user)\n    user_tps = user_tps.filter(\n        project__code=path_obj.code,\n    ).values_list('pootle_path', flat=True)\n    user_tps = list(path for path in user_tps\n                    if not path.startswith('/templates/'))\n    user_tps_regex = '^%s' % u'|'.join(user_tps)\n    sql_regex = 'REGEXP'\n    if connection.vendor == 'postgresql':\n        sql_regex = '~'\n\n    if filename:\n        query_pootle_path = query_pootle_path + filename\n        pootle_path = pootle_path + filename\n        resource_path = resource_path + filename\n\n        resources = Store.objects.live().extra(\n            where=[\n                'pootle_store_store.pootle_path LIKE %s',\n                'pootle_store_store.pootle_path ' + sql_regex + ' %s',\n            ], params=[query_pootle_path, user_tps_regex]\n        ).select_related('translation_project__language')\n    else:\n        resources = Directory.objects.live().extra(\n            where=[\n                'pootle_app_directory.pootle_path LIKE %s',\n                'pootle_app_directory.pootle_path ' + sql_regex + ' %s',\n            ], params=[query_pootle_path, user_tps_regex]\n        ).select_related('parent')\n\n    if not resources.exists():\n        raise Http404\n\n    request.store = None\n    request.directory = None\n    request.pootle_path = pootle_path\n\n    request.resource_obj = ProjectResource(resources, pootle_path)\n    request.resource_path = resource_path\n    request.ctx_obj = path_obj or request.resource_obj\n    request.ctx_path = ctx_path\n\n\ndef get_resource(func):\n    @wraps(func)\n    def wrapped(request, path_obj, dir_path, filename):\n        \"\"\"Gets resources associated to the current context.\"\"\"\n        try:\n            directory = getattr(path_obj, 'directory', path_obj)\n            if directory.is_project() and (dir_path or filename):\n                set_project_resource(request, path_obj, dir_path, filename)\n            else:\n                set_resource(request, path_obj, dir_path, filename)\n        except Http404:\n            if not request.is_ajax():\n                user_choice = request.COOKIES.get('user-choice', None)\n                url = None\n\n                if hasattr(request, 'redirect_url'):\n                    url = request.redirect_url\n                elif user_choice in ('language', 'resource',):\n                    project = (path_obj if isinstance(path_obj, Project)\n                                        else path_obj.project)\n                    url = reverse('pootle-project-browse',\n                                  args=[project.code, dir_path, filename])\n\n                if url is not None:\n                    response = redirect(url)\n\n                    if user_choice in ('language', 'resource',):\n                        # XXX: should we rather delete this in a single place?\n                        response.delete_cookie('user-choice')\n\n                    return response\n\n            raise Http404\n\n        return func(request, path_obj, dir_path, filename)\n\n    return wrapped\n\n\ndef permission_required(permission_code):\n    \"\"\"Checks for `permission_code` in the current context.\n\n    To retrieve the proper context, the `get_path_obj` decorator must be\n    used along with this decorator.\n    \"\"\"\n    def wrapped(func):\n        @wraps(func)\n        def _wrapped(request, *args, **kwargs):\n            path_obj = args[0]\n            directory = getattr(path_obj, 'directory', path_obj)\n\n            # HACKISH: some old code relies on\n            # `request.translation_project`, `request.language` etc.\n            # being set, so we need to set that too.\n            attr_name = CLS2ATTR.get(path_obj.__class__.__name__,\n                                     'path_obj')\n            setattr(request, attr_name, path_obj)\n\n            User = get_user_model()\n            request.profile = User.get(request.user)\n            request.permissions = get_matching_permissions(request.profile,\n                                                           directory)\n\n            if not permission_code:\n                return func(request, *args, **kwargs)\n\n            if not check_permission(permission_code, request):\n                raise PermissionDenied(\n                    _(\"Insufficient rights to access this page.\"),\n                )\n\n            return func(request, *args, **kwargs)\n        return _wrapped\n    return wrapped\n\n\ndef admin_required(func):\n    @wraps(func)\n    def wrapped(request, *args, **kwargs):\n        if not request.user.is_superuser:\n            raise PermissionDenied(\n                _(\"You do not have rights to administer Pootle.\")\n            )\n        return func(request, *args, **kwargs)\n\n    return wrapped\n", "path": "pootle/core/decorators.py"}]}