##// END OF EJS Templates
core: moved repo_list data to pyramid.
marcink -
r1667:be1f7a06 default
parent child Browse files
Show More
@@ -0,0 +1,103 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import json
22
23 from . import assert_and_get_content
24 from rhodecode.tests import TestController
25 from rhodecode.tests.fixture import Fixture
26 from rhodecode.model.db import Repository
27
28 fixture = Fixture()
29
30
31 def route_path(name, params=None, **kwargs):
32 import urllib
33
34 base_url = {
35 'repo_list_data': '/_repos',
36 }[name].format(**kwargs)
37
38 if params:
39 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
40 return base_url
41
42
43 class TestRepoListData(TestController):
44
45 def test_returns_list_of_repos_and_groups(self, xhr_header):
46 self.log_user()
47
48 response = self.app.get(
49 route_path('repo_list_data'),
50 extra_environ=xhr_header, status=200)
51 result = json.loads(response.body)['results']
52
53 repos, groups, commits = assert_and_get_content(result)
54
55 assert len(repos) == len(Repository.get_all())
56 assert len(groups) == 0
57 assert len(commits) == 0
58
59 def test_returns_list_of_repos_and_groups_filtered(self, xhr_header):
60 self.log_user()
61
62 response = self.app.get(
63 route_path('repo_list_data'),
64 params={'query': 'vcs_test_git'},
65 extra_environ=xhr_header, status=200)
66 result = json.loads(response.body)['results']
67
68 repos, groups, commits = assert_and_get_content(result)
69
70 assert len(repos) == len(Repository.query().filter(
71 Repository.repo_name.ilike('%vcs_test_git%')).all())
72 assert len(groups) == 0
73 assert len(commits) == 0
74
75 def test_returns_list_of_repos_and_groups_filtered_with_type(self, xhr_header):
76 self.log_user()
77
78 response = self.app.get(
79 route_path('repo_list_data'),
80 params={'query': 'vcs_test_git', 'repo_type': 'git'},
81 extra_environ=xhr_header, status=200)
82 result = json.loads(response.body)['results']
83
84 repos, groups, commits = assert_and_get_content(result)
85
86 assert len(repos) == len(Repository.query().filter(
87 Repository.repo_name.ilike('%vcs_test_git%')).all())
88 assert len(groups) == 0
89 assert len(commits) == 0
90
91 def test_returns_list_of_repos_non_ascii_query(self, xhr_header):
92 self.log_user()
93 response = self.app.get(
94 route_path('repo_list_data'),
95 params={'query': 'ć_vcs_test_ą', 'repo_type': 'git'},
96 extra_environ=xhr_header, status=200)
97 result = json.loads(response.body)['results']
98
99 repos, groups, commits = assert_and_get_content(result)
100
101 assert len(repos) == 0
102 assert len(groups) == 0
103 assert len(commits) == 0
@@ -1,33 +1,37 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 def includeme(config):
22 def includeme(config):
23
23
24 config.add_route(
24 config.add_route(
25 name='user_autocomplete_data',
25 name='user_autocomplete_data',
26 pattern='/_users')
26 pattern='/_users')
27
27
28 config.add_route(
28 config.add_route(
29 name='user_group_autocomplete_data',
29 name='user_group_autocomplete_data',
30 pattern='/_user_groups')
30 pattern='/_user_groups')
31
31
32 config.add_route(
33 name='repo_list_data',
34 pattern='/_repos')
35
32 # Scan module for configuration decorators.
36 # Scan module for configuration decorators.
33 config.scan()
37 config.scan()
@@ -1,19 +1,40 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 def assert_and_get_content(result):
23 repos = []
24 groups = []
25 commits = []
26 for data in result:
27 for data_item in data['children']:
28 assert data_item['id']
29 assert data_item['text']
30 assert data_item['url']
31 if data_item['type'] == 'repo':
32 repos.append(data_item)
33 elif data_item['type'] == 'group':
34 groups.append(data_item)
35 elif data_item['type'] == 'commit':
36 commits.append(data_item)
37 else:
38 raise Exception('invalid type %s' % data_item['type'])
39
40 return repos, groups, commits No newline at end of file
@@ -1,81 +1,138 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 from pyramid.view import view_config
23 from pyramid.view import view_config
24
24
25 from rhodecode.apps._base import BaseAppView
25 from rhodecode.apps._base import BaseAppView
26 from rhodecode.lib import helpers as h
26 from rhodecode.lib.auth import LoginRequired, NotAnonymous
27 from rhodecode.lib.auth import LoginRequired, NotAnonymous
27 from rhodecode.lib.utils2 import str2bool
28 from rhodecode.lib.utils2 import safe_unicode, str2bool
29 from rhodecode.model.db import func, Repository
28 from rhodecode.model.repo import RepoModel
30 from rhodecode.model.repo import RepoModel
31 from rhodecode.model.scm import ScmModel
32
29
33
30 log = logging.getLogger(__name__)
34 log = logging.getLogger(__name__)
31
35
32
36
33 class HomeView(BaseAppView):
37 class HomeView(BaseAppView):
34
38
35 def load_default_context(self):
39 def load_default_context(self):
36 c = self._get_local_tmpl_context()
40 c = self._get_local_tmpl_context()
37 c.user = c.auth_user.get_instance()
41 c.user = c.auth_user.get_instance()
38 self._register_global_c(c)
42 self._register_global_c(c)
39 return c
43 return c
40
44
41 @LoginRequired()
45 @LoginRequired()
42 @view_config(
46 @view_config(
43 route_name='user_autocomplete_data', request_method='GET',
47 route_name='user_autocomplete_data', request_method='GET',
44 renderer='json_ext', xhr=True)
48 renderer='json_ext', xhr=True)
45 def user_autocomplete_data(self):
49 def user_autocomplete_data(self):
46 query = self.request.GET.get('query')
50 query = self.request.GET.get('query')
47 active = str2bool(self.request.GET.get('active') or True)
51 active = str2bool(self.request.GET.get('active') or True)
48 include_groups = str2bool(self.request.GET.get('user_groups'))
52 include_groups = str2bool(self.request.GET.get('user_groups'))
49
53
50 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
54 log.debug('generating user list, query:%s, active:%s, with_groups:%s',
51 query, active, include_groups)
55 query, active, include_groups)
52
56
53 repo_model = RepoModel()
57 repo_model = RepoModel()
54 _users = repo_model.get_users(
58 _users = repo_model.get_users(
55 name_contains=query, only_active=active)
59 name_contains=query, only_active=active)
56
60
57 if include_groups:
61 if include_groups:
58 # extend with user groups
62 # extend with user groups
59 _user_groups = repo_model.get_user_groups(
63 _user_groups = repo_model.get_user_groups(
60 name_contains=query, only_active=active)
64 name_contains=query, only_active=active)
61 _users = _users + _user_groups
65 _users = _users + _user_groups
62
66
63 return {'suggestions': _users}
67 return {'suggestions': _users}
64
68
65 @LoginRequired()
69 @LoginRequired()
66 @NotAnonymous()
70 @NotAnonymous()
67 @view_config(
71 @view_config(
68 route_name='user_group_autocomplete_data', request_method='GET',
72 route_name='user_group_autocomplete_data', request_method='GET',
69 renderer='json_ext', xhr=True)
73 renderer='json_ext', xhr=True)
70 def user_group_autocomplete_data(self):
74 def user_group_autocomplete_data(self):
71 query = self.request.GET.get('query')
75 query = self.request.GET.get('query')
72 active = str2bool(self.request.GET.get('active') or True)
76 active = str2bool(self.request.GET.get('active') or True)
73 log.debug('generating user group list, query:%s, active:%s',
77 log.debug('generating user group list, query:%s, active:%s',
74 query, active)
78 query, active)
75
79
76 repo_model = RepoModel()
80 repo_model = RepoModel()
77 _user_groups = repo_model.get_user_groups(
81 _user_groups = repo_model.get_user_groups(
78 name_contains=query, only_active=active)
82 name_contains=query, only_active=active)
79 _user_groups = _user_groups
83 _user_groups = _user_groups
80
84
81 return {'suggestions': _user_groups}
85 return {'suggestions': _user_groups}
86
87 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
88 query = Repository.query()\
89 .order_by(func.length(Repository.repo_name))\
90 .order_by(Repository.repo_name)
91
92 if repo_type:
93 query = query.filter(Repository.repo_type == repo_type)
94
95 if name_contains:
96 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
97 query = query.filter(
98 Repository.repo_name.ilike(ilike_expression))
99 query = query.limit(limit)
100
101 all_repos = query.all()
102 # permission checks are inside this function
103 repo_iter = ScmModel().get_repos(all_repos)
104 return [
105 {
106 'id': obj['name'],
107 'text': obj['name'],
108 'type': 'repo',
109 'obj': obj['dbrepo'],
110 'url': h.url('summary_home', repo_name=obj['name'])
111 }
112 for obj in repo_iter]
113
114 @LoginRequired()
115 @view_config(
116 route_name='repo_list_data', request_method='GET',
117 renderer='json_ext', xhr=True)
118 def repo_list_data(self):
119 _ = self.request.translate
120
121 query = self.request.GET.get('query')
122 repo_type = self.request.GET.get('repo_type')
123 log.debug('generating repo list, query:%s, repo_type:%s',
124 query, repo_type)
125
126 res = []
127 repos = self._get_repo_list(query, repo_type=repo_type)
128 if repos:
129 res.append({
130 'text': _('Repositories'),
131 'children': repos
132 })
133
134 data = {
135 'more': False,
136 'results': res
137 }
138 return data
@@ -1,1148 +1,1146 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Routes configuration
22 Routes configuration
23
23
24 The more specific and detailed routes should be defined first so they
24 The more specific and detailed routes should be defined first so they
25 may take precedent over the more generic routes. For more information
25 may take precedent over the more generic routes. For more information
26 refer to the routes manual at http://routes.groovie.org/docs/
26 refer to the routes manual at http://routes.groovie.org/docs/
27
27
28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
29 and _route_name variable which uses some of stored naming here to do redirects.
29 and _route_name variable which uses some of stored naming here to do redirects.
30 """
30 """
31 import os
31 import os
32 import re
32 import re
33 from routes import Mapper
33 from routes import Mapper
34
34
35 from rhodecode.config import routing_links
35 from rhodecode.config import routing_links
36
36
37 # prefix for non repository related links needs to be prefixed with `/`
37 # prefix for non repository related links needs to be prefixed with `/`
38 ADMIN_PREFIX = '/_admin'
38 ADMIN_PREFIX = '/_admin'
39 STATIC_FILE_PREFIX = '/_static'
39 STATIC_FILE_PREFIX = '/_static'
40
40
41 # Default requirements for URL parts
41 # Default requirements for URL parts
42 URL_NAME_REQUIREMENTS = {
42 URL_NAME_REQUIREMENTS = {
43 # group name can have a slash in them, but they must not end with a slash
43 # group name can have a slash in them, but they must not end with a slash
44 'group_name': r'.*?[^/]',
44 'group_name': r'.*?[^/]',
45 'repo_group_name': r'.*?[^/]',
45 'repo_group_name': r'.*?[^/]',
46 # repo names can have a slash in them, but they must not end with a slash
46 # repo names can have a slash in them, but they must not end with a slash
47 'repo_name': r'.*?[^/]',
47 'repo_name': r'.*?[^/]',
48 # file path eats up everything at the end
48 # file path eats up everything at the end
49 'f_path': r'.*',
49 'f_path': r'.*',
50 # reference types
50 # reference types
51 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
51 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
52 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
52 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
53 }
53 }
54
54
55
55
56 def add_route_requirements(route_path, requirements):
56 def add_route_requirements(route_path, requirements):
57 """
57 """
58 Adds regex requirements to pyramid routes using a mapping dict
58 Adds regex requirements to pyramid routes using a mapping dict
59
59
60 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
60 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
61 '/{action}/{id:\d+}'
61 '/{action}/{id:\d+}'
62
62
63 """
63 """
64 for key, regex in requirements.items():
64 for key, regex in requirements.items():
65 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
65 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
66 return route_path
66 return route_path
67
67
68
68
69 class JSRoutesMapper(Mapper):
69 class JSRoutesMapper(Mapper):
70 """
70 """
71 Wrapper for routes.Mapper to make pyroutes compatible url definitions
71 Wrapper for routes.Mapper to make pyroutes compatible url definitions
72 """
72 """
73 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
73 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
74 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
74 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
75 def __init__(self, *args, **kw):
75 def __init__(self, *args, **kw):
76 super(JSRoutesMapper, self).__init__(*args, **kw)
76 super(JSRoutesMapper, self).__init__(*args, **kw)
77 self._jsroutes = []
77 self._jsroutes = []
78
78
79 def connect(self, *args, **kw):
79 def connect(self, *args, **kw):
80 """
80 """
81 Wrapper for connect to take an extra argument jsroute=True
81 Wrapper for connect to take an extra argument jsroute=True
82
82
83 :param jsroute: boolean, if True will add the route to the pyroutes list
83 :param jsroute: boolean, if True will add the route to the pyroutes list
84 """
84 """
85 if kw.pop('jsroute', False):
85 if kw.pop('jsroute', False):
86 if not self._named_route_regex.match(args[0]):
86 if not self._named_route_regex.match(args[0]):
87 raise Exception('only named routes can be added to pyroutes')
87 raise Exception('only named routes can be added to pyroutes')
88 self._jsroutes.append(args[0])
88 self._jsroutes.append(args[0])
89
89
90 super(JSRoutesMapper, self).connect(*args, **kw)
90 super(JSRoutesMapper, self).connect(*args, **kw)
91
91
92 def _extract_route_information(self, route):
92 def _extract_route_information(self, route):
93 """
93 """
94 Convert a route into tuple(name, path, args), eg:
94 Convert a route into tuple(name, path, args), eg:
95 ('show_user', '/profile/%(username)s', ['username'])
95 ('show_user', '/profile/%(username)s', ['username'])
96 """
96 """
97 routepath = route.routepath
97 routepath = route.routepath
98 def replace(matchobj):
98 def replace(matchobj):
99 if matchobj.group(1):
99 if matchobj.group(1):
100 return "%%(%s)s" % matchobj.group(1).split(':')[0]
100 return "%%(%s)s" % matchobj.group(1).split(':')[0]
101 else:
101 else:
102 return "%%(%s)s" % matchobj.group(2)
102 return "%%(%s)s" % matchobj.group(2)
103
103
104 routepath = self._argument_prog.sub(replace, routepath)
104 routepath = self._argument_prog.sub(replace, routepath)
105 return (
105 return (
106 route.name,
106 route.name,
107 routepath,
107 routepath,
108 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
108 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
109 for arg in self._argument_prog.findall(route.routepath)]
109 for arg in self._argument_prog.findall(route.routepath)]
110 )
110 )
111
111
112 def jsroutes(self):
112 def jsroutes(self):
113 """
113 """
114 Return a list of pyroutes.js compatible routes
114 Return a list of pyroutes.js compatible routes
115 """
115 """
116 for route_name in self._jsroutes:
116 for route_name in self._jsroutes:
117 yield self._extract_route_information(self._routenames[route_name])
117 yield self._extract_route_information(self._routenames[route_name])
118
118
119
119
120 def make_map(config):
120 def make_map(config):
121 """Create, configure and return the routes Mapper"""
121 """Create, configure and return the routes Mapper"""
122 rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'],
122 rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'],
123 always_scan=config['debug'])
123 always_scan=config['debug'])
124 rmap.minimization = False
124 rmap.minimization = False
125 rmap.explicit = False
125 rmap.explicit = False
126
126
127 from rhodecode.lib.utils2 import str2bool
127 from rhodecode.lib.utils2 import str2bool
128 from rhodecode.model import repo, repo_group
128 from rhodecode.model import repo, repo_group
129
129
130 def check_repo(environ, match_dict):
130 def check_repo(environ, match_dict):
131 """
131 """
132 check for valid repository for proper 404 handling
132 check for valid repository for proper 404 handling
133
133
134 :param environ:
134 :param environ:
135 :param match_dict:
135 :param match_dict:
136 """
136 """
137 repo_name = match_dict.get('repo_name')
137 repo_name = match_dict.get('repo_name')
138
138
139 if match_dict.get('f_path'):
139 if match_dict.get('f_path'):
140 # fix for multiple initial slashes that causes errors
140 # fix for multiple initial slashes that causes errors
141 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
141 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
142 repo_model = repo.RepoModel()
142 repo_model = repo.RepoModel()
143 by_name_match = repo_model.get_by_repo_name(repo_name)
143 by_name_match = repo_model.get_by_repo_name(repo_name)
144 # if we match quickly from database, short circuit the operation,
144 # if we match quickly from database, short circuit the operation,
145 # and validate repo based on the type.
145 # and validate repo based on the type.
146 if by_name_match:
146 if by_name_match:
147 return True
147 return True
148
148
149 by_id_match = repo_model.get_repo_by_id(repo_name)
149 by_id_match = repo_model.get_repo_by_id(repo_name)
150 if by_id_match:
150 if by_id_match:
151 repo_name = by_id_match.repo_name
151 repo_name = by_id_match.repo_name
152 match_dict['repo_name'] = repo_name
152 match_dict['repo_name'] = repo_name
153 return True
153 return True
154
154
155 return False
155 return False
156
156
157 def check_group(environ, match_dict):
157 def check_group(environ, match_dict):
158 """
158 """
159 check for valid repository group path for proper 404 handling
159 check for valid repository group path for proper 404 handling
160
160
161 :param environ:
161 :param environ:
162 :param match_dict:
162 :param match_dict:
163 """
163 """
164 repo_group_name = match_dict.get('group_name')
164 repo_group_name = match_dict.get('group_name')
165 repo_group_model = repo_group.RepoGroupModel()
165 repo_group_model = repo_group.RepoGroupModel()
166 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
166 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
167 if by_name_match:
167 if by_name_match:
168 return True
168 return True
169
169
170 return False
170 return False
171
171
172 def check_user_group(environ, match_dict):
172 def check_user_group(environ, match_dict):
173 """
173 """
174 check for valid user group for proper 404 handling
174 check for valid user group for proper 404 handling
175
175
176 :param environ:
176 :param environ:
177 :param match_dict:
177 :param match_dict:
178 """
178 """
179 return True
179 return True
180
180
181 def check_int(environ, match_dict):
181 def check_int(environ, match_dict):
182 return match_dict.get('id').isdigit()
182 return match_dict.get('id').isdigit()
183
183
184
184
185 #==========================================================================
185 #==========================================================================
186 # CUSTOM ROUTES HERE
186 # CUSTOM ROUTES HERE
187 #==========================================================================
187 #==========================================================================
188
188
189 # MAIN PAGE
189 # MAIN PAGE
190 rmap.connect('home', '/', controller='home', action='index', jsroute=True)
190 rmap.connect('home', '/', controller='home', action='index', jsroute=True)
191 rmap.connect('goto_switcher_data', '/_goto_data', controller='home',
191 rmap.connect('goto_switcher_data', '/_goto_data', controller='home',
192 action='goto_switcher_data')
192 action='goto_switcher_data')
193 rmap.connect('repo_list_data', '/_repos', controller='home',
194 action='repo_list_data')
195
193
196 # TODO: johbo: Static links, to be replaced by our redirection mechanism
194 # TODO: johbo: Static links, to be replaced by our redirection mechanism
197 rmap.connect('rst_help',
195 rmap.connect('rst_help',
198 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
196 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
199 _static=True)
197 _static=True)
200 rmap.connect('markdown_help',
198 rmap.connect('markdown_help',
201 'http://daringfireball.net/projects/markdown/syntax',
199 'http://daringfireball.net/projects/markdown/syntax',
202 _static=True)
200 _static=True)
203 rmap.connect('rhodecode_official', 'https://rhodecode.com', _static=True)
201 rmap.connect('rhodecode_official', 'https://rhodecode.com', _static=True)
204 rmap.connect('rhodecode_support', 'https://rhodecode.com/help/', _static=True)
202 rmap.connect('rhodecode_support', 'https://rhodecode.com/help/', _static=True)
205 rmap.connect('rhodecode_translations', 'https://rhodecode.com/translate/enterprise', _static=True)
203 rmap.connect('rhodecode_translations', 'https://rhodecode.com/translate/enterprise', _static=True)
206 # TODO: anderson - making this a static link since redirect won't play
204 # TODO: anderson - making this a static link since redirect won't play
207 # nice with POST requests
205 # nice with POST requests
208 rmap.connect('enterprise_license_convert_from_old',
206 rmap.connect('enterprise_license_convert_from_old',
209 'https://rhodecode.com/u/license-upgrade',
207 'https://rhodecode.com/u/license-upgrade',
210 _static=True)
208 _static=True)
211
209
212 routing_links.connect_redirection_links(rmap)
210 routing_links.connect_redirection_links(rmap)
213
211
214 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
212 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
215 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
213 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
216
214
217 # ADMIN REPOSITORY ROUTES
215 # ADMIN REPOSITORY ROUTES
218 with rmap.submapper(path_prefix=ADMIN_PREFIX,
216 with rmap.submapper(path_prefix=ADMIN_PREFIX,
219 controller='admin/repos') as m:
217 controller='admin/repos') as m:
220 m.connect('repos', '/repos',
218 m.connect('repos', '/repos',
221 action='create', conditions={'method': ['POST']})
219 action='create', conditions={'method': ['POST']})
222 m.connect('repos', '/repos',
220 m.connect('repos', '/repos',
223 action='index', conditions={'method': ['GET']})
221 action='index', conditions={'method': ['GET']})
224 m.connect('new_repo', '/create_repository', jsroute=True,
222 m.connect('new_repo', '/create_repository', jsroute=True,
225 action='create_repository', conditions={'method': ['GET']})
223 action='create_repository', conditions={'method': ['GET']})
226 m.connect('/repos/{repo_name}',
224 m.connect('/repos/{repo_name}',
227 action='update', conditions={'method': ['PUT'],
225 action='update', conditions={'method': ['PUT'],
228 'function': check_repo},
226 'function': check_repo},
229 requirements=URL_NAME_REQUIREMENTS)
227 requirements=URL_NAME_REQUIREMENTS)
230 m.connect('delete_repo', '/repos/{repo_name}',
228 m.connect('delete_repo', '/repos/{repo_name}',
231 action='delete', conditions={'method': ['DELETE']},
229 action='delete', conditions={'method': ['DELETE']},
232 requirements=URL_NAME_REQUIREMENTS)
230 requirements=URL_NAME_REQUIREMENTS)
233 m.connect('repo', '/repos/{repo_name}',
231 m.connect('repo', '/repos/{repo_name}',
234 action='show', conditions={'method': ['GET'],
232 action='show', conditions={'method': ['GET'],
235 'function': check_repo},
233 'function': check_repo},
236 requirements=URL_NAME_REQUIREMENTS)
234 requirements=URL_NAME_REQUIREMENTS)
237
235
238 # ADMIN REPOSITORY GROUPS ROUTES
236 # ADMIN REPOSITORY GROUPS ROUTES
239 with rmap.submapper(path_prefix=ADMIN_PREFIX,
237 with rmap.submapper(path_prefix=ADMIN_PREFIX,
240 controller='admin/repo_groups') as m:
238 controller='admin/repo_groups') as m:
241 m.connect('repo_groups', '/repo_groups',
239 m.connect('repo_groups', '/repo_groups',
242 action='create', conditions={'method': ['POST']})
240 action='create', conditions={'method': ['POST']})
243 m.connect('repo_groups', '/repo_groups',
241 m.connect('repo_groups', '/repo_groups',
244 action='index', conditions={'method': ['GET']})
242 action='index', conditions={'method': ['GET']})
245 m.connect('new_repo_group', '/repo_groups/new',
243 m.connect('new_repo_group', '/repo_groups/new',
246 action='new', conditions={'method': ['GET']})
244 action='new', conditions={'method': ['GET']})
247 m.connect('update_repo_group', '/repo_groups/{group_name}',
245 m.connect('update_repo_group', '/repo_groups/{group_name}',
248 action='update', conditions={'method': ['PUT'],
246 action='update', conditions={'method': ['PUT'],
249 'function': check_group},
247 'function': check_group},
250 requirements=URL_NAME_REQUIREMENTS)
248 requirements=URL_NAME_REQUIREMENTS)
251
249
252 # EXTRAS REPO GROUP ROUTES
250 # EXTRAS REPO GROUP ROUTES
253 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
251 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
254 action='edit',
252 action='edit',
255 conditions={'method': ['GET'], 'function': check_group},
253 conditions={'method': ['GET'], 'function': check_group},
256 requirements=URL_NAME_REQUIREMENTS)
254 requirements=URL_NAME_REQUIREMENTS)
257 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
255 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
258 action='edit',
256 action='edit',
259 conditions={'method': ['PUT'], 'function': check_group},
257 conditions={'method': ['PUT'], 'function': check_group},
260 requirements=URL_NAME_REQUIREMENTS)
258 requirements=URL_NAME_REQUIREMENTS)
261
259
262 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
260 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
263 action='edit_repo_group_advanced',
261 action='edit_repo_group_advanced',
264 conditions={'method': ['GET'], 'function': check_group},
262 conditions={'method': ['GET'], 'function': check_group},
265 requirements=URL_NAME_REQUIREMENTS)
263 requirements=URL_NAME_REQUIREMENTS)
266 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
264 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
267 action='edit_repo_group_advanced',
265 action='edit_repo_group_advanced',
268 conditions={'method': ['PUT'], 'function': check_group},
266 conditions={'method': ['PUT'], 'function': check_group},
269 requirements=URL_NAME_REQUIREMENTS)
267 requirements=URL_NAME_REQUIREMENTS)
270
268
271 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
269 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
272 action='edit_repo_group_perms',
270 action='edit_repo_group_perms',
273 conditions={'method': ['GET'], 'function': check_group},
271 conditions={'method': ['GET'], 'function': check_group},
274 requirements=URL_NAME_REQUIREMENTS)
272 requirements=URL_NAME_REQUIREMENTS)
275 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
273 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
276 action='update_perms',
274 action='update_perms',
277 conditions={'method': ['PUT'], 'function': check_group},
275 conditions={'method': ['PUT'], 'function': check_group},
278 requirements=URL_NAME_REQUIREMENTS)
276 requirements=URL_NAME_REQUIREMENTS)
279
277
280 m.connect('delete_repo_group', '/repo_groups/{group_name}',
278 m.connect('delete_repo_group', '/repo_groups/{group_name}',
281 action='delete', conditions={'method': ['DELETE'],
279 action='delete', conditions={'method': ['DELETE'],
282 'function': check_group},
280 'function': check_group},
283 requirements=URL_NAME_REQUIREMENTS)
281 requirements=URL_NAME_REQUIREMENTS)
284
282
285 # ADMIN USER ROUTES
283 # ADMIN USER ROUTES
286 with rmap.submapper(path_prefix=ADMIN_PREFIX,
284 with rmap.submapper(path_prefix=ADMIN_PREFIX,
287 controller='admin/users') as m:
285 controller='admin/users') as m:
288 m.connect('users', '/users',
286 m.connect('users', '/users',
289 action='create', conditions={'method': ['POST']})
287 action='create', conditions={'method': ['POST']})
290 m.connect('new_user', '/users/new',
288 m.connect('new_user', '/users/new',
291 action='new', conditions={'method': ['GET']})
289 action='new', conditions={'method': ['GET']})
292 m.connect('update_user', '/users/{user_id}',
290 m.connect('update_user', '/users/{user_id}',
293 action='update', conditions={'method': ['PUT']})
291 action='update', conditions={'method': ['PUT']})
294 m.connect('delete_user', '/users/{user_id}',
292 m.connect('delete_user', '/users/{user_id}',
295 action='delete', conditions={'method': ['DELETE']})
293 action='delete', conditions={'method': ['DELETE']})
296 m.connect('edit_user', '/users/{user_id}/edit',
294 m.connect('edit_user', '/users/{user_id}/edit',
297 action='edit', conditions={'method': ['GET']}, jsroute=True)
295 action='edit', conditions={'method': ['GET']}, jsroute=True)
298 m.connect('user', '/users/{user_id}',
296 m.connect('user', '/users/{user_id}',
299 action='show', conditions={'method': ['GET']})
297 action='show', conditions={'method': ['GET']})
300 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
298 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
301 action='reset_password', conditions={'method': ['POST']})
299 action='reset_password', conditions={'method': ['POST']})
302 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
300 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
303 action='create_personal_repo_group', conditions={'method': ['POST']})
301 action='create_personal_repo_group', conditions={'method': ['POST']})
304
302
305 # EXTRAS USER ROUTES
303 # EXTRAS USER ROUTES
306 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
304 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
307 action='edit_advanced', conditions={'method': ['GET']})
305 action='edit_advanced', conditions={'method': ['GET']})
308 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
306 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
309 action='update_advanced', conditions={'method': ['PUT']})
307 action='update_advanced', conditions={'method': ['PUT']})
310
308
311 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
309 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
312 action='edit_global_perms', conditions={'method': ['GET']})
310 action='edit_global_perms', conditions={'method': ['GET']})
313 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
311 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
314 action='update_global_perms', conditions={'method': ['PUT']})
312 action='update_global_perms', conditions={'method': ['PUT']})
315
313
316 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
314 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
317 action='edit_perms_summary', conditions={'method': ['GET']})
315 action='edit_perms_summary', conditions={'method': ['GET']})
318
316
319 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
317 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
320 action='edit_emails', conditions={'method': ['GET']})
318 action='edit_emails', conditions={'method': ['GET']})
321 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
319 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
322 action='add_email', conditions={'method': ['PUT']})
320 action='add_email', conditions={'method': ['PUT']})
323 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
321 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
324 action='delete_email', conditions={'method': ['DELETE']})
322 action='delete_email', conditions={'method': ['DELETE']})
325
323
326 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
324 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
327 action='edit_ips', conditions={'method': ['GET']})
325 action='edit_ips', conditions={'method': ['GET']})
328 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
326 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
329 action='add_ip', conditions={'method': ['PUT']})
327 action='add_ip', conditions={'method': ['PUT']})
330 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
328 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
331 action='delete_ip', conditions={'method': ['DELETE']})
329 action='delete_ip', conditions={'method': ['DELETE']})
332
330
333 # ADMIN USER GROUPS REST ROUTES
331 # ADMIN USER GROUPS REST ROUTES
334 with rmap.submapper(path_prefix=ADMIN_PREFIX,
332 with rmap.submapper(path_prefix=ADMIN_PREFIX,
335 controller='admin/user_groups') as m:
333 controller='admin/user_groups') as m:
336 m.connect('users_groups', '/user_groups',
334 m.connect('users_groups', '/user_groups',
337 action='create', conditions={'method': ['POST']})
335 action='create', conditions={'method': ['POST']})
338 m.connect('users_groups', '/user_groups',
336 m.connect('users_groups', '/user_groups',
339 action='index', conditions={'method': ['GET']})
337 action='index', conditions={'method': ['GET']})
340 m.connect('new_users_group', '/user_groups/new',
338 m.connect('new_users_group', '/user_groups/new',
341 action='new', conditions={'method': ['GET']})
339 action='new', conditions={'method': ['GET']})
342 m.connect('update_users_group', '/user_groups/{user_group_id}',
340 m.connect('update_users_group', '/user_groups/{user_group_id}',
343 action='update', conditions={'method': ['PUT']})
341 action='update', conditions={'method': ['PUT']})
344 m.connect('delete_users_group', '/user_groups/{user_group_id}',
342 m.connect('delete_users_group', '/user_groups/{user_group_id}',
345 action='delete', conditions={'method': ['DELETE']})
343 action='delete', conditions={'method': ['DELETE']})
346 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
344 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
347 action='edit', conditions={'method': ['GET']},
345 action='edit', conditions={'method': ['GET']},
348 function=check_user_group)
346 function=check_user_group)
349
347
350 # EXTRAS USER GROUP ROUTES
348 # EXTRAS USER GROUP ROUTES
351 m.connect('edit_user_group_global_perms',
349 m.connect('edit_user_group_global_perms',
352 '/user_groups/{user_group_id}/edit/global_permissions',
350 '/user_groups/{user_group_id}/edit/global_permissions',
353 action='edit_global_perms', conditions={'method': ['GET']})
351 action='edit_global_perms', conditions={'method': ['GET']})
354 m.connect('edit_user_group_global_perms',
352 m.connect('edit_user_group_global_perms',
355 '/user_groups/{user_group_id}/edit/global_permissions',
353 '/user_groups/{user_group_id}/edit/global_permissions',
356 action='update_global_perms', conditions={'method': ['PUT']})
354 action='update_global_perms', conditions={'method': ['PUT']})
357 m.connect('edit_user_group_perms_summary',
355 m.connect('edit_user_group_perms_summary',
358 '/user_groups/{user_group_id}/edit/permissions_summary',
356 '/user_groups/{user_group_id}/edit/permissions_summary',
359 action='edit_perms_summary', conditions={'method': ['GET']})
357 action='edit_perms_summary', conditions={'method': ['GET']})
360
358
361 m.connect('edit_user_group_perms',
359 m.connect('edit_user_group_perms',
362 '/user_groups/{user_group_id}/edit/permissions',
360 '/user_groups/{user_group_id}/edit/permissions',
363 action='edit_perms', conditions={'method': ['GET']})
361 action='edit_perms', conditions={'method': ['GET']})
364 m.connect('edit_user_group_perms',
362 m.connect('edit_user_group_perms',
365 '/user_groups/{user_group_id}/edit/permissions',
363 '/user_groups/{user_group_id}/edit/permissions',
366 action='update_perms', conditions={'method': ['PUT']})
364 action='update_perms', conditions={'method': ['PUT']})
367
365
368 m.connect('edit_user_group_advanced',
366 m.connect('edit_user_group_advanced',
369 '/user_groups/{user_group_id}/edit/advanced',
367 '/user_groups/{user_group_id}/edit/advanced',
370 action='edit_advanced', conditions={'method': ['GET']})
368 action='edit_advanced', conditions={'method': ['GET']})
371
369
372 m.connect('edit_user_group_advanced_sync',
370 m.connect('edit_user_group_advanced_sync',
373 '/user_groups/{user_group_id}/edit/advanced/sync',
371 '/user_groups/{user_group_id}/edit/advanced/sync',
374 action='edit_advanced_set_synchronization', conditions={'method': ['POST']})
372 action='edit_advanced_set_synchronization', conditions={'method': ['POST']})
375
373
376 m.connect('edit_user_group_members',
374 m.connect('edit_user_group_members',
377 '/user_groups/{user_group_id}/edit/members', jsroute=True,
375 '/user_groups/{user_group_id}/edit/members', jsroute=True,
378 action='user_group_members', conditions={'method': ['GET']})
376 action='user_group_members', conditions={'method': ['GET']})
379
377
380 # ADMIN PERMISSIONS ROUTES
378 # ADMIN PERMISSIONS ROUTES
381 with rmap.submapper(path_prefix=ADMIN_PREFIX,
379 with rmap.submapper(path_prefix=ADMIN_PREFIX,
382 controller='admin/permissions') as m:
380 controller='admin/permissions') as m:
383 m.connect('admin_permissions_application', '/permissions/application',
381 m.connect('admin_permissions_application', '/permissions/application',
384 action='permission_application_update', conditions={'method': ['POST']})
382 action='permission_application_update', conditions={'method': ['POST']})
385 m.connect('admin_permissions_application', '/permissions/application',
383 m.connect('admin_permissions_application', '/permissions/application',
386 action='permission_application', conditions={'method': ['GET']})
384 action='permission_application', conditions={'method': ['GET']})
387
385
388 m.connect('admin_permissions_global', '/permissions/global',
386 m.connect('admin_permissions_global', '/permissions/global',
389 action='permission_global_update', conditions={'method': ['POST']})
387 action='permission_global_update', conditions={'method': ['POST']})
390 m.connect('admin_permissions_global', '/permissions/global',
388 m.connect('admin_permissions_global', '/permissions/global',
391 action='permission_global', conditions={'method': ['GET']})
389 action='permission_global', conditions={'method': ['GET']})
392
390
393 m.connect('admin_permissions_object', '/permissions/object',
391 m.connect('admin_permissions_object', '/permissions/object',
394 action='permission_objects_update', conditions={'method': ['POST']})
392 action='permission_objects_update', conditions={'method': ['POST']})
395 m.connect('admin_permissions_object', '/permissions/object',
393 m.connect('admin_permissions_object', '/permissions/object',
396 action='permission_objects', conditions={'method': ['GET']})
394 action='permission_objects', conditions={'method': ['GET']})
397
395
398 m.connect('admin_permissions_ips', '/permissions/ips',
396 m.connect('admin_permissions_ips', '/permissions/ips',
399 action='permission_ips', conditions={'method': ['POST']})
397 action='permission_ips', conditions={'method': ['POST']})
400 m.connect('admin_permissions_ips', '/permissions/ips',
398 m.connect('admin_permissions_ips', '/permissions/ips',
401 action='permission_ips', conditions={'method': ['GET']})
399 action='permission_ips', conditions={'method': ['GET']})
402
400
403 m.connect('admin_permissions_overview', '/permissions/overview',
401 m.connect('admin_permissions_overview', '/permissions/overview',
404 action='permission_perms', conditions={'method': ['GET']})
402 action='permission_perms', conditions={'method': ['GET']})
405
403
406 # ADMIN DEFAULTS REST ROUTES
404 # ADMIN DEFAULTS REST ROUTES
407 with rmap.submapper(path_prefix=ADMIN_PREFIX,
405 with rmap.submapper(path_prefix=ADMIN_PREFIX,
408 controller='admin/defaults') as m:
406 controller='admin/defaults') as m:
409 m.connect('admin_defaults_repositories', '/defaults/repositories',
407 m.connect('admin_defaults_repositories', '/defaults/repositories',
410 action='update_repository_defaults', conditions={'method': ['POST']})
408 action='update_repository_defaults', conditions={'method': ['POST']})
411 m.connect('admin_defaults_repositories', '/defaults/repositories',
409 m.connect('admin_defaults_repositories', '/defaults/repositories',
412 action='index', conditions={'method': ['GET']})
410 action='index', conditions={'method': ['GET']})
413
411
414 # ADMIN DEBUG STYLE ROUTES
412 # ADMIN DEBUG STYLE ROUTES
415 if str2bool(config.get('debug_style')):
413 if str2bool(config.get('debug_style')):
416 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
414 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
417 controller='debug_style') as m:
415 controller='debug_style') as m:
418 m.connect('debug_style_home', '',
416 m.connect('debug_style_home', '',
419 action='index', conditions={'method': ['GET']})
417 action='index', conditions={'method': ['GET']})
420 m.connect('debug_style_template', '/t/{t_path}',
418 m.connect('debug_style_template', '/t/{t_path}',
421 action='template', conditions={'method': ['GET']})
419 action='template', conditions={'method': ['GET']})
422
420
423 # ADMIN SETTINGS ROUTES
421 # ADMIN SETTINGS ROUTES
424 with rmap.submapper(path_prefix=ADMIN_PREFIX,
422 with rmap.submapper(path_prefix=ADMIN_PREFIX,
425 controller='admin/settings') as m:
423 controller='admin/settings') as m:
426
424
427 # default
425 # default
428 m.connect('admin_settings', '/settings',
426 m.connect('admin_settings', '/settings',
429 action='settings_global_update',
427 action='settings_global_update',
430 conditions={'method': ['POST']})
428 conditions={'method': ['POST']})
431 m.connect('admin_settings', '/settings',
429 m.connect('admin_settings', '/settings',
432 action='settings_global', conditions={'method': ['GET']})
430 action='settings_global', conditions={'method': ['GET']})
433
431
434 m.connect('admin_settings_vcs', '/settings/vcs',
432 m.connect('admin_settings_vcs', '/settings/vcs',
435 action='settings_vcs_update',
433 action='settings_vcs_update',
436 conditions={'method': ['POST']})
434 conditions={'method': ['POST']})
437 m.connect('admin_settings_vcs', '/settings/vcs',
435 m.connect('admin_settings_vcs', '/settings/vcs',
438 action='settings_vcs',
436 action='settings_vcs',
439 conditions={'method': ['GET']})
437 conditions={'method': ['GET']})
440 m.connect('admin_settings_vcs', '/settings/vcs',
438 m.connect('admin_settings_vcs', '/settings/vcs',
441 action='delete_svn_pattern',
439 action='delete_svn_pattern',
442 conditions={'method': ['DELETE']})
440 conditions={'method': ['DELETE']})
443
441
444 m.connect('admin_settings_mapping', '/settings/mapping',
442 m.connect('admin_settings_mapping', '/settings/mapping',
445 action='settings_mapping_update',
443 action='settings_mapping_update',
446 conditions={'method': ['POST']})
444 conditions={'method': ['POST']})
447 m.connect('admin_settings_mapping', '/settings/mapping',
445 m.connect('admin_settings_mapping', '/settings/mapping',
448 action='settings_mapping', conditions={'method': ['GET']})
446 action='settings_mapping', conditions={'method': ['GET']})
449
447
450 m.connect('admin_settings_global', '/settings/global',
448 m.connect('admin_settings_global', '/settings/global',
451 action='settings_global_update',
449 action='settings_global_update',
452 conditions={'method': ['POST']})
450 conditions={'method': ['POST']})
453 m.connect('admin_settings_global', '/settings/global',
451 m.connect('admin_settings_global', '/settings/global',
454 action='settings_global', conditions={'method': ['GET']})
452 action='settings_global', conditions={'method': ['GET']})
455
453
456 m.connect('admin_settings_visual', '/settings/visual',
454 m.connect('admin_settings_visual', '/settings/visual',
457 action='settings_visual_update',
455 action='settings_visual_update',
458 conditions={'method': ['POST']})
456 conditions={'method': ['POST']})
459 m.connect('admin_settings_visual', '/settings/visual',
457 m.connect('admin_settings_visual', '/settings/visual',
460 action='settings_visual', conditions={'method': ['GET']})
458 action='settings_visual', conditions={'method': ['GET']})
461
459
462 m.connect('admin_settings_issuetracker',
460 m.connect('admin_settings_issuetracker',
463 '/settings/issue-tracker', action='settings_issuetracker',
461 '/settings/issue-tracker', action='settings_issuetracker',
464 conditions={'method': ['GET']})
462 conditions={'method': ['GET']})
465 m.connect('admin_settings_issuetracker_save',
463 m.connect('admin_settings_issuetracker_save',
466 '/settings/issue-tracker/save',
464 '/settings/issue-tracker/save',
467 action='settings_issuetracker_save',
465 action='settings_issuetracker_save',
468 conditions={'method': ['POST']})
466 conditions={'method': ['POST']})
469 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
467 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
470 action='settings_issuetracker_test',
468 action='settings_issuetracker_test',
471 conditions={'method': ['POST']})
469 conditions={'method': ['POST']})
472 m.connect('admin_issuetracker_delete',
470 m.connect('admin_issuetracker_delete',
473 '/settings/issue-tracker/delete',
471 '/settings/issue-tracker/delete',
474 action='settings_issuetracker_delete',
472 action='settings_issuetracker_delete',
475 conditions={'method': ['DELETE']})
473 conditions={'method': ['DELETE']})
476
474
477 m.connect('admin_settings_email', '/settings/email',
475 m.connect('admin_settings_email', '/settings/email',
478 action='settings_email_update',
476 action='settings_email_update',
479 conditions={'method': ['POST']})
477 conditions={'method': ['POST']})
480 m.connect('admin_settings_email', '/settings/email',
478 m.connect('admin_settings_email', '/settings/email',
481 action='settings_email', conditions={'method': ['GET']})
479 action='settings_email', conditions={'method': ['GET']})
482
480
483 m.connect('admin_settings_hooks', '/settings/hooks',
481 m.connect('admin_settings_hooks', '/settings/hooks',
484 action='settings_hooks_update',
482 action='settings_hooks_update',
485 conditions={'method': ['POST', 'DELETE']})
483 conditions={'method': ['POST', 'DELETE']})
486 m.connect('admin_settings_hooks', '/settings/hooks',
484 m.connect('admin_settings_hooks', '/settings/hooks',
487 action='settings_hooks', conditions={'method': ['GET']})
485 action='settings_hooks', conditions={'method': ['GET']})
488
486
489 m.connect('admin_settings_search', '/settings/search',
487 m.connect('admin_settings_search', '/settings/search',
490 action='settings_search', conditions={'method': ['GET']})
488 action='settings_search', conditions={'method': ['GET']})
491
489
492 m.connect('admin_settings_supervisor', '/settings/supervisor',
490 m.connect('admin_settings_supervisor', '/settings/supervisor',
493 action='settings_supervisor', conditions={'method': ['GET']})
491 action='settings_supervisor', conditions={'method': ['GET']})
494 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
492 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
495 action='settings_supervisor_log', conditions={'method': ['GET']})
493 action='settings_supervisor_log', conditions={'method': ['GET']})
496
494
497 m.connect('admin_settings_labs', '/settings/labs',
495 m.connect('admin_settings_labs', '/settings/labs',
498 action='settings_labs_update',
496 action='settings_labs_update',
499 conditions={'method': ['POST']})
497 conditions={'method': ['POST']})
500 m.connect('admin_settings_labs', '/settings/labs',
498 m.connect('admin_settings_labs', '/settings/labs',
501 action='settings_labs', conditions={'method': ['GET']})
499 action='settings_labs', conditions={'method': ['GET']})
502
500
503 # ADMIN MY ACCOUNT
501 # ADMIN MY ACCOUNT
504 with rmap.submapper(path_prefix=ADMIN_PREFIX,
502 with rmap.submapper(path_prefix=ADMIN_PREFIX,
505 controller='admin/my_account') as m:
503 controller='admin/my_account') as m:
506
504
507 m.connect('my_account_edit', '/my_account/edit',
505 m.connect('my_account_edit', '/my_account/edit',
508 action='my_account_edit', conditions={'method': ['GET']})
506 action='my_account_edit', conditions={'method': ['GET']})
509 m.connect('my_account', '/my_account/update',
507 m.connect('my_account', '/my_account/update',
510 action='my_account_update', conditions={'method': ['POST']})
508 action='my_account_update', conditions={'method': ['POST']})
511
509
512 # NOTE(marcink): this needs to be kept for password force flag to be
510 # NOTE(marcink): this needs to be kept for password force flag to be
513 # handler, remove after migration to pyramid
511 # handler, remove after migration to pyramid
514 m.connect('my_account_password', '/my_account/password',
512 m.connect('my_account_password', '/my_account/password',
515 action='my_account_password', conditions={'method': ['GET']})
513 action='my_account_password', conditions={'method': ['GET']})
516
514
517 m.connect('my_account_repos', '/my_account/repos',
515 m.connect('my_account_repos', '/my_account/repos',
518 action='my_account_repos', conditions={'method': ['GET']})
516 action='my_account_repos', conditions={'method': ['GET']})
519
517
520 m.connect('my_account_watched', '/my_account/watched',
518 m.connect('my_account_watched', '/my_account/watched',
521 action='my_account_watched', conditions={'method': ['GET']})
519 action='my_account_watched', conditions={'method': ['GET']})
522
520
523 m.connect('my_account_pullrequests', '/my_account/pull_requests',
521 m.connect('my_account_pullrequests', '/my_account/pull_requests',
524 action='my_account_pullrequests', conditions={'method': ['GET']})
522 action='my_account_pullrequests', conditions={'method': ['GET']})
525
523
526 m.connect('my_account_perms', '/my_account/perms',
524 m.connect('my_account_perms', '/my_account/perms',
527 action='my_account_perms', conditions={'method': ['GET']})
525 action='my_account_perms', conditions={'method': ['GET']})
528
526
529 m.connect('my_account_emails', '/my_account/emails',
527 m.connect('my_account_emails', '/my_account/emails',
530 action='my_account_emails', conditions={'method': ['GET']})
528 action='my_account_emails', conditions={'method': ['GET']})
531 m.connect('my_account_emails', '/my_account/emails',
529 m.connect('my_account_emails', '/my_account/emails',
532 action='my_account_emails_add', conditions={'method': ['POST']})
530 action='my_account_emails_add', conditions={'method': ['POST']})
533 m.connect('my_account_emails', '/my_account/emails',
531 m.connect('my_account_emails', '/my_account/emails',
534 action='my_account_emails_delete', conditions={'method': ['DELETE']})
532 action='my_account_emails_delete', conditions={'method': ['DELETE']})
535
533
536 m.connect('my_account_notifications', '/my_account/notifications',
534 m.connect('my_account_notifications', '/my_account/notifications',
537 action='my_notifications',
535 action='my_notifications',
538 conditions={'method': ['GET']})
536 conditions={'method': ['GET']})
539 m.connect('my_account_notifications_toggle_visibility',
537 m.connect('my_account_notifications_toggle_visibility',
540 '/my_account/toggle_visibility',
538 '/my_account/toggle_visibility',
541 action='my_notifications_toggle_visibility',
539 action='my_notifications_toggle_visibility',
542 conditions={'method': ['POST']})
540 conditions={'method': ['POST']})
543 m.connect('my_account_notifications_test_channelstream',
541 m.connect('my_account_notifications_test_channelstream',
544 '/my_account/test_channelstream',
542 '/my_account/test_channelstream',
545 action='my_account_notifications_test_channelstream',
543 action='my_account_notifications_test_channelstream',
546 conditions={'method': ['POST']})
544 conditions={'method': ['POST']})
547
545
548 # NOTIFICATION REST ROUTES
546 # NOTIFICATION REST ROUTES
549 with rmap.submapper(path_prefix=ADMIN_PREFIX,
547 with rmap.submapper(path_prefix=ADMIN_PREFIX,
550 controller='admin/notifications') as m:
548 controller='admin/notifications') as m:
551 m.connect('notifications', '/notifications',
549 m.connect('notifications', '/notifications',
552 action='index', conditions={'method': ['GET']})
550 action='index', conditions={'method': ['GET']})
553 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
551 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
554 action='mark_all_read', conditions={'method': ['POST']})
552 action='mark_all_read', conditions={'method': ['POST']})
555 m.connect('/notifications/{notification_id}',
553 m.connect('/notifications/{notification_id}',
556 action='update', conditions={'method': ['PUT']})
554 action='update', conditions={'method': ['PUT']})
557 m.connect('/notifications/{notification_id}',
555 m.connect('/notifications/{notification_id}',
558 action='delete', conditions={'method': ['DELETE']})
556 action='delete', conditions={'method': ['DELETE']})
559 m.connect('notification', '/notifications/{notification_id}',
557 m.connect('notification', '/notifications/{notification_id}',
560 action='show', conditions={'method': ['GET']})
558 action='show', conditions={'method': ['GET']})
561
559
562 # ADMIN GIST
560 # ADMIN GIST
563 with rmap.submapper(path_prefix=ADMIN_PREFIX,
561 with rmap.submapper(path_prefix=ADMIN_PREFIX,
564 controller='admin/gists') as m:
562 controller='admin/gists') as m:
565 m.connect('gists', '/gists',
563 m.connect('gists', '/gists',
566 action='create', conditions={'method': ['POST']})
564 action='create', conditions={'method': ['POST']})
567 m.connect('gists', '/gists', jsroute=True,
565 m.connect('gists', '/gists', jsroute=True,
568 action='index', conditions={'method': ['GET']})
566 action='index', conditions={'method': ['GET']})
569 m.connect('new_gist', '/gists/new', jsroute=True,
567 m.connect('new_gist', '/gists/new', jsroute=True,
570 action='new', conditions={'method': ['GET']})
568 action='new', conditions={'method': ['GET']})
571
569
572 m.connect('/gists/{gist_id}',
570 m.connect('/gists/{gist_id}',
573 action='delete', conditions={'method': ['DELETE']})
571 action='delete', conditions={'method': ['DELETE']})
574 m.connect('edit_gist', '/gists/{gist_id}/edit',
572 m.connect('edit_gist', '/gists/{gist_id}/edit',
575 action='edit_form', conditions={'method': ['GET']})
573 action='edit_form', conditions={'method': ['GET']})
576 m.connect('edit_gist', '/gists/{gist_id}/edit',
574 m.connect('edit_gist', '/gists/{gist_id}/edit',
577 action='edit', conditions={'method': ['POST']})
575 action='edit', conditions={'method': ['POST']})
578 m.connect(
576 m.connect(
579 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision',
577 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision',
580 action='check_revision', conditions={'method': ['GET']})
578 action='check_revision', conditions={'method': ['GET']})
581
579
582 m.connect('gist', '/gists/{gist_id}',
580 m.connect('gist', '/gists/{gist_id}',
583 action='show', conditions={'method': ['GET']})
581 action='show', conditions={'method': ['GET']})
584 m.connect('gist_rev', '/gists/{gist_id}/{revision}',
582 m.connect('gist_rev', '/gists/{gist_id}/{revision}',
585 revision='tip',
583 revision='tip',
586 action='show', conditions={'method': ['GET']})
584 action='show', conditions={'method': ['GET']})
587 m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}',
585 m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}',
588 revision='tip',
586 revision='tip',
589 action='show', conditions={'method': ['GET']})
587 action='show', conditions={'method': ['GET']})
590 m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}',
588 m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}',
591 revision='tip',
589 revision='tip',
592 action='show', conditions={'method': ['GET']},
590 action='show', conditions={'method': ['GET']},
593 requirements=URL_NAME_REQUIREMENTS)
591 requirements=URL_NAME_REQUIREMENTS)
594
592
595 # ADMIN MAIN PAGES
593 # ADMIN MAIN PAGES
596 with rmap.submapper(path_prefix=ADMIN_PREFIX,
594 with rmap.submapper(path_prefix=ADMIN_PREFIX,
597 controller='admin/admin') as m:
595 controller='admin/admin') as m:
598 m.connect('admin_home', '', action='index')
596 m.connect('admin_home', '', action='index')
599 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
597 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
600 action='add_repo')
598 action='add_repo')
601 m.connect(
599 m.connect(
602 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}',
600 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}',
603 action='pull_requests')
601 action='pull_requests')
604 m.connect(
602 m.connect(
605 'pull_requests_global_1', '/pull-requests/{pull_request_id:[0-9]+}',
603 'pull_requests_global_1', '/pull-requests/{pull_request_id:[0-9]+}',
606 action='pull_requests')
604 action='pull_requests')
607 m.connect(
605 m.connect(
608 'pull_requests_global', '/pull-request/{pull_request_id:[0-9]+}',
606 'pull_requests_global', '/pull-request/{pull_request_id:[0-9]+}',
609 action='pull_requests')
607 action='pull_requests')
610
608
611 # USER JOURNAL
609 # USER JOURNAL
612 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
610 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
613 controller='journal', action='index')
611 controller='journal', action='index')
614 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
612 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
615 controller='journal', action='journal_rss')
613 controller='journal', action='journal_rss')
616 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
614 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
617 controller='journal', action='journal_atom')
615 controller='journal', action='journal_atom')
618
616
619 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
617 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
620 controller='journal', action='public_journal')
618 controller='journal', action='public_journal')
621
619
622 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
620 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
623 controller='journal', action='public_journal_rss')
621 controller='journal', action='public_journal_rss')
624
622
625 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
623 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
626 controller='journal', action='public_journal_rss')
624 controller='journal', action='public_journal_rss')
627
625
628 rmap.connect('public_journal_atom',
626 rmap.connect('public_journal_atom',
629 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
627 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
630 action='public_journal_atom')
628 action='public_journal_atom')
631
629
632 rmap.connect('public_journal_atom_old',
630 rmap.connect('public_journal_atom_old',
633 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
631 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
634 action='public_journal_atom')
632 action='public_journal_atom')
635
633
636 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
634 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
637 controller='journal', action='toggle_following', jsroute=True,
635 controller='journal', action='toggle_following', jsroute=True,
638 conditions={'method': ['POST']})
636 conditions={'method': ['POST']})
639
637
640 # FULL TEXT SEARCH
638 # FULL TEXT SEARCH
641 rmap.connect('search', '%s/search' % (ADMIN_PREFIX,),
639 rmap.connect('search', '%s/search' % (ADMIN_PREFIX,),
642 controller='search')
640 controller='search')
643 rmap.connect('search_repo_home', '/{repo_name}/search',
641 rmap.connect('search_repo_home', '/{repo_name}/search',
644 controller='search',
642 controller='search',
645 action='index',
643 action='index',
646 conditions={'function': check_repo},
644 conditions={'function': check_repo},
647 requirements=URL_NAME_REQUIREMENTS)
645 requirements=URL_NAME_REQUIREMENTS)
648
646
649 # FEEDS
647 # FEEDS
650 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
648 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
651 controller='feed', action='rss',
649 controller='feed', action='rss',
652 conditions={'function': check_repo},
650 conditions={'function': check_repo},
653 requirements=URL_NAME_REQUIREMENTS)
651 requirements=URL_NAME_REQUIREMENTS)
654
652
655 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
653 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
656 controller='feed', action='atom',
654 controller='feed', action='atom',
657 conditions={'function': check_repo},
655 conditions={'function': check_repo},
658 requirements=URL_NAME_REQUIREMENTS)
656 requirements=URL_NAME_REQUIREMENTS)
659
657
660 #==========================================================================
658 #==========================================================================
661 # REPOSITORY ROUTES
659 # REPOSITORY ROUTES
662 #==========================================================================
660 #==========================================================================
663
661
664 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
662 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
665 controller='admin/repos', action='repo_creating',
663 controller='admin/repos', action='repo_creating',
666 requirements=URL_NAME_REQUIREMENTS)
664 requirements=URL_NAME_REQUIREMENTS)
667 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
665 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
668 controller='admin/repos', action='repo_check',
666 controller='admin/repos', action='repo_check',
669 requirements=URL_NAME_REQUIREMENTS)
667 requirements=URL_NAME_REQUIREMENTS)
670
668
671 rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}',
669 rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}',
672 controller='summary', action='repo_stats',
670 controller='summary', action='repo_stats',
673 conditions={'function': check_repo},
671 conditions={'function': check_repo},
674 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
672 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
675
673
676 rmap.connect('repo_refs_data', '/{repo_name}/refs-data',
674 rmap.connect('repo_refs_data', '/{repo_name}/refs-data',
677 controller='summary', action='repo_refs_data',
675 controller='summary', action='repo_refs_data',
678 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
676 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
679 rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog',
677 rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog',
680 controller='summary', action='repo_refs_changelog_data',
678 controller='summary', action='repo_refs_changelog_data',
681 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
679 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
682 rmap.connect('repo_default_reviewers_data', '/{repo_name}/default-reviewers',
680 rmap.connect('repo_default_reviewers_data', '/{repo_name}/default-reviewers',
683 controller='summary', action='repo_default_reviewers_data',
681 controller='summary', action='repo_default_reviewers_data',
684 jsroute=True, requirements=URL_NAME_REQUIREMENTS)
682 jsroute=True, requirements=URL_NAME_REQUIREMENTS)
685
683
686 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
684 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
687 controller='changeset', revision='tip',
685 controller='changeset', revision='tip',
688 conditions={'function': check_repo},
686 conditions={'function': check_repo},
689 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
687 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
690 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
688 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
691 controller='changeset', revision='tip', action='changeset_children',
689 controller='changeset', revision='tip', action='changeset_children',
692 conditions={'function': check_repo},
690 conditions={'function': check_repo},
693 requirements=URL_NAME_REQUIREMENTS)
691 requirements=URL_NAME_REQUIREMENTS)
694 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
692 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
695 controller='changeset', revision='tip', action='changeset_parents',
693 controller='changeset', revision='tip', action='changeset_parents',
696 conditions={'function': check_repo},
694 conditions={'function': check_repo},
697 requirements=URL_NAME_REQUIREMENTS)
695 requirements=URL_NAME_REQUIREMENTS)
698
696
699 # repo edit options
697 # repo edit options
700 rmap.connect('edit_repo', '/{repo_name}/settings', jsroute=True,
698 rmap.connect('edit_repo', '/{repo_name}/settings', jsroute=True,
701 controller='admin/repos', action='edit',
699 controller='admin/repos', action='edit',
702 conditions={'method': ['GET'], 'function': check_repo},
700 conditions={'method': ['GET'], 'function': check_repo},
703 requirements=URL_NAME_REQUIREMENTS)
701 requirements=URL_NAME_REQUIREMENTS)
704
702
705 rmap.connect('edit_repo_perms', '/{repo_name}/settings/permissions',
703 rmap.connect('edit_repo_perms', '/{repo_name}/settings/permissions',
706 jsroute=True,
704 jsroute=True,
707 controller='admin/repos', action='edit_permissions',
705 controller='admin/repos', action='edit_permissions',
708 conditions={'method': ['GET'], 'function': check_repo},
706 conditions={'method': ['GET'], 'function': check_repo},
709 requirements=URL_NAME_REQUIREMENTS)
707 requirements=URL_NAME_REQUIREMENTS)
710 rmap.connect('edit_repo_perms_update', '/{repo_name}/settings/permissions',
708 rmap.connect('edit_repo_perms_update', '/{repo_name}/settings/permissions',
711 controller='admin/repos', action='edit_permissions_update',
709 controller='admin/repos', action='edit_permissions_update',
712 conditions={'method': ['PUT'], 'function': check_repo},
710 conditions={'method': ['PUT'], 'function': check_repo},
713 requirements=URL_NAME_REQUIREMENTS)
711 requirements=URL_NAME_REQUIREMENTS)
714
712
715 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
713 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
716 controller='admin/repos', action='edit_fields',
714 controller='admin/repos', action='edit_fields',
717 conditions={'method': ['GET'], 'function': check_repo},
715 conditions={'method': ['GET'], 'function': check_repo},
718 requirements=URL_NAME_REQUIREMENTS)
716 requirements=URL_NAME_REQUIREMENTS)
719 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
717 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
720 controller='admin/repos', action='create_repo_field',
718 controller='admin/repos', action='create_repo_field',
721 conditions={'method': ['PUT'], 'function': check_repo},
719 conditions={'method': ['PUT'], 'function': check_repo},
722 requirements=URL_NAME_REQUIREMENTS)
720 requirements=URL_NAME_REQUIREMENTS)
723 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
721 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
724 controller='admin/repos', action='delete_repo_field',
722 controller='admin/repos', action='delete_repo_field',
725 conditions={'method': ['DELETE'], 'function': check_repo},
723 conditions={'method': ['DELETE'], 'function': check_repo},
726 requirements=URL_NAME_REQUIREMENTS)
724 requirements=URL_NAME_REQUIREMENTS)
727
725
728 rmap.connect('edit_repo_advanced', '/{repo_name}/settings/advanced',
726 rmap.connect('edit_repo_advanced', '/{repo_name}/settings/advanced',
729 controller='admin/repos', action='edit_advanced',
727 controller='admin/repos', action='edit_advanced',
730 conditions={'method': ['GET'], 'function': check_repo},
728 conditions={'method': ['GET'], 'function': check_repo},
731 requirements=URL_NAME_REQUIREMENTS)
729 requirements=URL_NAME_REQUIREMENTS)
732
730
733 rmap.connect('edit_repo_advanced_locking', '/{repo_name}/settings/advanced/locking',
731 rmap.connect('edit_repo_advanced_locking', '/{repo_name}/settings/advanced/locking',
734 controller='admin/repos', action='edit_advanced_locking',
732 controller='admin/repos', action='edit_advanced_locking',
735 conditions={'method': ['PUT'], 'function': check_repo},
733 conditions={'method': ['PUT'], 'function': check_repo},
736 requirements=URL_NAME_REQUIREMENTS)
734 requirements=URL_NAME_REQUIREMENTS)
737 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
735 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
738 controller='admin/repos', action='toggle_locking',
736 controller='admin/repos', action='toggle_locking',
739 conditions={'method': ['GET'], 'function': check_repo},
737 conditions={'method': ['GET'], 'function': check_repo},
740 requirements=URL_NAME_REQUIREMENTS)
738 requirements=URL_NAME_REQUIREMENTS)
741
739
742 rmap.connect('edit_repo_advanced_journal', '/{repo_name}/settings/advanced/journal',
740 rmap.connect('edit_repo_advanced_journal', '/{repo_name}/settings/advanced/journal',
743 controller='admin/repos', action='edit_advanced_journal',
741 controller='admin/repos', action='edit_advanced_journal',
744 conditions={'method': ['PUT'], 'function': check_repo},
742 conditions={'method': ['PUT'], 'function': check_repo},
745 requirements=URL_NAME_REQUIREMENTS)
743 requirements=URL_NAME_REQUIREMENTS)
746
744
747 rmap.connect('edit_repo_advanced_fork', '/{repo_name}/settings/advanced/fork',
745 rmap.connect('edit_repo_advanced_fork', '/{repo_name}/settings/advanced/fork',
748 controller='admin/repos', action='edit_advanced_fork',
746 controller='admin/repos', action='edit_advanced_fork',
749 conditions={'method': ['PUT'], 'function': check_repo},
747 conditions={'method': ['PUT'], 'function': check_repo},
750 requirements=URL_NAME_REQUIREMENTS)
748 requirements=URL_NAME_REQUIREMENTS)
751
749
752 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
750 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
753 controller='admin/repos', action='edit_caches_form',
751 controller='admin/repos', action='edit_caches_form',
754 conditions={'method': ['GET'], 'function': check_repo},
752 conditions={'method': ['GET'], 'function': check_repo},
755 requirements=URL_NAME_REQUIREMENTS)
753 requirements=URL_NAME_REQUIREMENTS)
756 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
754 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
757 controller='admin/repos', action='edit_caches',
755 controller='admin/repos', action='edit_caches',
758 conditions={'method': ['PUT'], 'function': check_repo},
756 conditions={'method': ['PUT'], 'function': check_repo},
759 requirements=URL_NAME_REQUIREMENTS)
757 requirements=URL_NAME_REQUIREMENTS)
760
758
761 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
759 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
762 controller='admin/repos', action='edit_remote_form',
760 controller='admin/repos', action='edit_remote_form',
763 conditions={'method': ['GET'], 'function': check_repo},
761 conditions={'method': ['GET'], 'function': check_repo},
764 requirements=URL_NAME_REQUIREMENTS)
762 requirements=URL_NAME_REQUIREMENTS)
765 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
763 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
766 controller='admin/repos', action='edit_remote',
764 controller='admin/repos', action='edit_remote',
767 conditions={'method': ['PUT'], 'function': check_repo},
765 conditions={'method': ['PUT'], 'function': check_repo},
768 requirements=URL_NAME_REQUIREMENTS)
766 requirements=URL_NAME_REQUIREMENTS)
769
767
770 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
768 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
771 controller='admin/repos', action='edit_statistics_form',
769 controller='admin/repos', action='edit_statistics_form',
772 conditions={'method': ['GET'], 'function': check_repo},
770 conditions={'method': ['GET'], 'function': check_repo},
773 requirements=URL_NAME_REQUIREMENTS)
771 requirements=URL_NAME_REQUIREMENTS)
774 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
772 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
775 controller='admin/repos', action='edit_statistics',
773 controller='admin/repos', action='edit_statistics',
776 conditions={'method': ['PUT'], 'function': check_repo},
774 conditions={'method': ['PUT'], 'function': check_repo},
777 requirements=URL_NAME_REQUIREMENTS)
775 requirements=URL_NAME_REQUIREMENTS)
778 rmap.connect('repo_settings_issuetracker',
776 rmap.connect('repo_settings_issuetracker',
779 '/{repo_name}/settings/issue-tracker',
777 '/{repo_name}/settings/issue-tracker',
780 controller='admin/repos', action='repo_issuetracker',
778 controller='admin/repos', action='repo_issuetracker',
781 conditions={'method': ['GET'], 'function': check_repo},
779 conditions={'method': ['GET'], 'function': check_repo},
782 requirements=URL_NAME_REQUIREMENTS)
780 requirements=URL_NAME_REQUIREMENTS)
783 rmap.connect('repo_issuetracker_test',
781 rmap.connect('repo_issuetracker_test',
784 '/{repo_name}/settings/issue-tracker/test',
782 '/{repo_name}/settings/issue-tracker/test',
785 controller='admin/repos', action='repo_issuetracker_test',
783 controller='admin/repos', action='repo_issuetracker_test',
786 conditions={'method': ['POST'], 'function': check_repo},
784 conditions={'method': ['POST'], 'function': check_repo},
787 requirements=URL_NAME_REQUIREMENTS)
785 requirements=URL_NAME_REQUIREMENTS)
788 rmap.connect('repo_issuetracker_delete',
786 rmap.connect('repo_issuetracker_delete',
789 '/{repo_name}/settings/issue-tracker/delete',
787 '/{repo_name}/settings/issue-tracker/delete',
790 controller='admin/repos', action='repo_issuetracker_delete',
788 controller='admin/repos', action='repo_issuetracker_delete',
791 conditions={'method': ['DELETE'], 'function': check_repo},
789 conditions={'method': ['DELETE'], 'function': check_repo},
792 requirements=URL_NAME_REQUIREMENTS)
790 requirements=URL_NAME_REQUIREMENTS)
793 rmap.connect('repo_issuetracker_save',
791 rmap.connect('repo_issuetracker_save',
794 '/{repo_name}/settings/issue-tracker/save',
792 '/{repo_name}/settings/issue-tracker/save',
795 controller='admin/repos', action='repo_issuetracker_save',
793 controller='admin/repos', action='repo_issuetracker_save',
796 conditions={'method': ['POST'], 'function': check_repo},
794 conditions={'method': ['POST'], 'function': check_repo},
797 requirements=URL_NAME_REQUIREMENTS)
795 requirements=URL_NAME_REQUIREMENTS)
798 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
796 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
799 controller='admin/repos', action='repo_settings_vcs_update',
797 controller='admin/repos', action='repo_settings_vcs_update',
800 conditions={'method': ['POST'], 'function': check_repo},
798 conditions={'method': ['POST'], 'function': check_repo},
801 requirements=URL_NAME_REQUIREMENTS)
799 requirements=URL_NAME_REQUIREMENTS)
802 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
800 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
803 controller='admin/repos', action='repo_settings_vcs',
801 controller='admin/repos', action='repo_settings_vcs',
804 conditions={'method': ['GET'], 'function': check_repo},
802 conditions={'method': ['GET'], 'function': check_repo},
805 requirements=URL_NAME_REQUIREMENTS)
803 requirements=URL_NAME_REQUIREMENTS)
806 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
804 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
807 controller='admin/repos', action='repo_delete_svn_pattern',
805 controller='admin/repos', action='repo_delete_svn_pattern',
808 conditions={'method': ['DELETE'], 'function': check_repo},
806 conditions={'method': ['DELETE'], 'function': check_repo},
809 requirements=URL_NAME_REQUIREMENTS)
807 requirements=URL_NAME_REQUIREMENTS)
810 rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest',
808 rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest',
811 controller='admin/repos', action='repo_settings_pullrequest',
809 controller='admin/repos', action='repo_settings_pullrequest',
812 conditions={'method': ['GET', 'POST'], 'function': check_repo},
810 conditions={'method': ['GET', 'POST'], 'function': check_repo},
813 requirements=URL_NAME_REQUIREMENTS)
811 requirements=URL_NAME_REQUIREMENTS)
814
812
815 # still working url for backward compat.
813 # still working url for backward compat.
816 rmap.connect('raw_changeset_home_depraced',
814 rmap.connect('raw_changeset_home_depraced',
817 '/{repo_name}/raw-changeset/{revision}',
815 '/{repo_name}/raw-changeset/{revision}',
818 controller='changeset', action='changeset_raw',
816 controller='changeset', action='changeset_raw',
819 revision='tip', conditions={'function': check_repo},
817 revision='tip', conditions={'function': check_repo},
820 requirements=URL_NAME_REQUIREMENTS)
818 requirements=URL_NAME_REQUIREMENTS)
821
819
822 # new URLs
820 # new URLs
823 rmap.connect('changeset_raw_home',
821 rmap.connect('changeset_raw_home',
824 '/{repo_name}/changeset-diff/{revision}',
822 '/{repo_name}/changeset-diff/{revision}',
825 controller='changeset', action='changeset_raw',
823 controller='changeset', action='changeset_raw',
826 revision='tip', conditions={'function': check_repo},
824 revision='tip', conditions={'function': check_repo},
827 requirements=URL_NAME_REQUIREMENTS)
825 requirements=URL_NAME_REQUIREMENTS)
828
826
829 rmap.connect('changeset_patch_home',
827 rmap.connect('changeset_patch_home',
830 '/{repo_name}/changeset-patch/{revision}',
828 '/{repo_name}/changeset-patch/{revision}',
831 controller='changeset', action='changeset_patch',
829 controller='changeset', action='changeset_patch',
832 revision='tip', conditions={'function': check_repo},
830 revision='tip', conditions={'function': check_repo},
833 requirements=URL_NAME_REQUIREMENTS)
831 requirements=URL_NAME_REQUIREMENTS)
834
832
835 rmap.connect('changeset_download_home',
833 rmap.connect('changeset_download_home',
836 '/{repo_name}/changeset-download/{revision}',
834 '/{repo_name}/changeset-download/{revision}',
837 controller='changeset', action='changeset_download',
835 controller='changeset', action='changeset_download',
838 revision='tip', conditions={'function': check_repo},
836 revision='tip', conditions={'function': check_repo},
839 requirements=URL_NAME_REQUIREMENTS)
837 requirements=URL_NAME_REQUIREMENTS)
840
838
841 rmap.connect('changeset_comment',
839 rmap.connect('changeset_comment',
842 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
840 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
843 controller='changeset', revision='tip', action='comment',
841 controller='changeset', revision='tip', action='comment',
844 conditions={'function': check_repo},
842 conditions={'function': check_repo},
845 requirements=URL_NAME_REQUIREMENTS)
843 requirements=URL_NAME_REQUIREMENTS)
846
844
847 rmap.connect('changeset_comment_preview',
845 rmap.connect('changeset_comment_preview',
848 '/{repo_name}/changeset/comment/preview', jsroute=True,
846 '/{repo_name}/changeset/comment/preview', jsroute=True,
849 controller='changeset', action='preview_comment',
847 controller='changeset', action='preview_comment',
850 conditions={'function': check_repo, 'method': ['POST']},
848 conditions={'function': check_repo, 'method': ['POST']},
851 requirements=URL_NAME_REQUIREMENTS)
849 requirements=URL_NAME_REQUIREMENTS)
852
850
853 rmap.connect('changeset_comment_delete',
851 rmap.connect('changeset_comment_delete',
854 '/{repo_name}/changeset/comment/{comment_id}/delete',
852 '/{repo_name}/changeset/comment/{comment_id}/delete',
855 controller='changeset', action='delete_comment',
853 controller='changeset', action='delete_comment',
856 conditions={'function': check_repo, 'method': ['DELETE']},
854 conditions={'function': check_repo, 'method': ['DELETE']},
857 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
855 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
858
856
859 rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
857 rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
860 controller='changeset', action='changeset_info',
858 controller='changeset', action='changeset_info',
861 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
859 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
862
860
863 rmap.connect('compare_home',
861 rmap.connect('compare_home',
864 '/{repo_name}/compare',
862 '/{repo_name}/compare',
865 controller='compare', action='index',
863 controller='compare', action='index',
866 conditions={'function': check_repo},
864 conditions={'function': check_repo},
867 requirements=URL_NAME_REQUIREMENTS)
865 requirements=URL_NAME_REQUIREMENTS)
868
866
869 rmap.connect('compare_url',
867 rmap.connect('compare_url',
870 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
868 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
871 controller='compare', action='compare',
869 controller='compare', action='compare',
872 conditions={'function': check_repo},
870 conditions={'function': check_repo},
873 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
871 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
874
872
875 rmap.connect('pullrequest_home',
873 rmap.connect('pullrequest_home',
876 '/{repo_name}/pull-request/new', controller='pullrequests',
874 '/{repo_name}/pull-request/new', controller='pullrequests',
877 action='index', conditions={'function': check_repo,
875 action='index', conditions={'function': check_repo,
878 'method': ['GET']},
876 'method': ['GET']},
879 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
877 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
880
878
881 rmap.connect('pullrequest',
879 rmap.connect('pullrequest',
882 '/{repo_name}/pull-request/new', controller='pullrequests',
880 '/{repo_name}/pull-request/new', controller='pullrequests',
883 action='create', conditions={'function': check_repo,
881 action='create', conditions={'function': check_repo,
884 'method': ['POST']},
882 'method': ['POST']},
885 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
883 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
886
884
887 rmap.connect('pullrequest_repo_refs',
885 rmap.connect('pullrequest_repo_refs',
888 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
886 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
889 controller='pullrequests',
887 controller='pullrequests',
890 action='get_repo_refs',
888 action='get_repo_refs',
891 conditions={'function': check_repo, 'method': ['GET']},
889 conditions={'function': check_repo, 'method': ['GET']},
892 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
890 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
893
891
894 rmap.connect('pullrequest_repo_destinations',
892 rmap.connect('pullrequest_repo_destinations',
895 '/{repo_name}/pull-request/repo-destinations',
893 '/{repo_name}/pull-request/repo-destinations',
896 controller='pullrequests',
894 controller='pullrequests',
897 action='get_repo_destinations',
895 action='get_repo_destinations',
898 conditions={'function': check_repo, 'method': ['GET']},
896 conditions={'function': check_repo, 'method': ['GET']},
899 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
897 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
900
898
901 rmap.connect('pullrequest_show',
899 rmap.connect('pullrequest_show',
902 '/{repo_name}/pull-request/{pull_request_id}',
900 '/{repo_name}/pull-request/{pull_request_id}',
903 controller='pullrequests',
901 controller='pullrequests',
904 action='show', conditions={'function': check_repo,
902 action='show', conditions={'function': check_repo,
905 'method': ['GET']},
903 'method': ['GET']},
906 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
904 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
907
905
908 rmap.connect('pullrequest_update',
906 rmap.connect('pullrequest_update',
909 '/{repo_name}/pull-request/{pull_request_id}',
907 '/{repo_name}/pull-request/{pull_request_id}',
910 controller='pullrequests',
908 controller='pullrequests',
911 action='update', conditions={'function': check_repo,
909 action='update', conditions={'function': check_repo,
912 'method': ['PUT']},
910 'method': ['PUT']},
913 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
911 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
914
912
915 rmap.connect('pullrequest_merge',
913 rmap.connect('pullrequest_merge',
916 '/{repo_name}/pull-request/{pull_request_id}',
914 '/{repo_name}/pull-request/{pull_request_id}',
917 controller='pullrequests',
915 controller='pullrequests',
918 action='merge', conditions={'function': check_repo,
916 action='merge', conditions={'function': check_repo,
919 'method': ['POST']},
917 'method': ['POST']},
920 requirements=URL_NAME_REQUIREMENTS)
918 requirements=URL_NAME_REQUIREMENTS)
921
919
922 rmap.connect('pullrequest_delete',
920 rmap.connect('pullrequest_delete',
923 '/{repo_name}/pull-request/{pull_request_id}',
921 '/{repo_name}/pull-request/{pull_request_id}',
924 controller='pullrequests',
922 controller='pullrequests',
925 action='delete', conditions={'function': check_repo,
923 action='delete', conditions={'function': check_repo,
926 'method': ['DELETE']},
924 'method': ['DELETE']},
927 requirements=URL_NAME_REQUIREMENTS)
925 requirements=URL_NAME_REQUIREMENTS)
928
926
929 rmap.connect('pullrequest_show_all',
927 rmap.connect('pullrequest_show_all',
930 '/{repo_name}/pull-request',
928 '/{repo_name}/pull-request',
931 controller='pullrequests',
929 controller='pullrequests',
932 action='show_all', conditions={'function': check_repo,
930 action='show_all', conditions={'function': check_repo,
933 'method': ['GET']},
931 'method': ['GET']},
934 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
932 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
935
933
936 rmap.connect('pullrequest_comment',
934 rmap.connect('pullrequest_comment',
937 '/{repo_name}/pull-request-comment/{pull_request_id}',
935 '/{repo_name}/pull-request-comment/{pull_request_id}',
938 controller='pullrequests',
936 controller='pullrequests',
939 action='comment', conditions={'function': check_repo,
937 action='comment', conditions={'function': check_repo,
940 'method': ['POST']},
938 'method': ['POST']},
941 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
939 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
942
940
943 rmap.connect('pullrequest_comment_delete',
941 rmap.connect('pullrequest_comment_delete',
944 '/{repo_name}/pull-request-comment/{comment_id}/delete',
942 '/{repo_name}/pull-request-comment/{comment_id}/delete',
945 controller='pullrequests', action='delete_comment',
943 controller='pullrequests', action='delete_comment',
946 conditions={'function': check_repo, 'method': ['DELETE']},
944 conditions={'function': check_repo, 'method': ['DELETE']},
947 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
945 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
948
946
949 rmap.connect('summary_home_explicit', '/{repo_name}/summary',
947 rmap.connect('summary_home_explicit', '/{repo_name}/summary',
950 controller='summary', conditions={'function': check_repo},
948 controller='summary', conditions={'function': check_repo},
951 requirements=URL_NAME_REQUIREMENTS)
949 requirements=URL_NAME_REQUIREMENTS)
952
950
953 rmap.connect('branches_home', '/{repo_name}/branches',
951 rmap.connect('branches_home', '/{repo_name}/branches',
954 controller='branches', conditions={'function': check_repo},
952 controller='branches', conditions={'function': check_repo},
955 requirements=URL_NAME_REQUIREMENTS)
953 requirements=URL_NAME_REQUIREMENTS)
956
954
957 rmap.connect('tags_home', '/{repo_name}/tags',
955 rmap.connect('tags_home', '/{repo_name}/tags',
958 controller='tags', conditions={'function': check_repo},
956 controller='tags', conditions={'function': check_repo},
959 requirements=URL_NAME_REQUIREMENTS)
957 requirements=URL_NAME_REQUIREMENTS)
960
958
961 rmap.connect('bookmarks_home', '/{repo_name}/bookmarks',
959 rmap.connect('bookmarks_home', '/{repo_name}/bookmarks',
962 controller='bookmarks', conditions={'function': check_repo},
960 controller='bookmarks', conditions={'function': check_repo},
963 requirements=URL_NAME_REQUIREMENTS)
961 requirements=URL_NAME_REQUIREMENTS)
964
962
965 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
963 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
966 controller='changelog', conditions={'function': check_repo},
964 controller='changelog', conditions={'function': check_repo},
967 requirements=URL_NAME_REQUIREMENTS)
965 requirements=URL_NAME_REQUIREMENTS)
968
966
969 rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary',
967 rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary',
970 controller='changelog', action='changelog_summary',
968 controller='changelog', action='changelog_summary',
971 conditions={'function': check_repo},
969 conditions={'function': check_repo},
972 requirements=URL_NAME_REQUIREMENTS)
970 requirements=URL_NAME_REQUIREMENTS)
973
971
974 rmap.connect('changelog_file_home',
972 rmap.connect('changelog_file_home',
975 '/{repo_name}/changelog/{revision}/{f_path}',
973 '/{repo_name}/changelog/{revision}/{f_path}',
976 controller='changelog', f_path=None,
974 controller='changelog', f_path=None,
977 conditions={'function': check_repo},
975 conditions={'function': check_repo},
978 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
976 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
979
977
980 rmap.connect('changelog_elements', '/{repo_name}/changelog_details',
978 rmap.connect('changelog_elements', '/{repo_name}/changelog_details',
981 controller='changelog', action='changelog_elements',
979 controller='changelog', action='changelog_elements',
982 conditions={'function': check_repo},
980 conditions={'function': check_repo},
983 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
981 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
984
982
985 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
983 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
986 controller='files', revision='tip', f_path='',
984 controller='files', revision='tip', f_path='',
987 conditions={'function': check_repo},
985 conditions={'function': check_repo},
988 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
986 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
989
987
990 rmap.connect('files_home_simple_catchrev',
988 rmap.connect('files_home_simple_catchrev',
991 '/{repo_name}/files/{revision}',
989 '/{repo_name}/files/{revision}',
992 controller='files', revision='tip', f_path='',
990 controller='files', revision='tip', f_path='',
993 conditions={'function': check_repo},
991 conditions={'function': check_repo},
994 requirements=URL_NAME_REQUIREMENTS)
992 requirements=URL_NAME_REQUIREMENTS)
995
993
996 rmap.connect('files_home_simple_catchall',
994 rmap.connect('files_home_simple_catchall',
997 '/{repo_name}/files',
995 '/{repo_name}/files',
998 controller='files', revision='tip', f_path='',
996 controller='files', revision='tip', f_path='',
999 conditions={'function': check_repo},
997 conditions={'function': check_repo},
1000 requirements=URL_NAME_REQUIREMENTS)
998 requirements=URL_NAME_REQUIREMENTS)
1001
999
1002 rmap.connect('files_history_home',
1000 rmap.connect('files_history_home',
1003 '/{repo_name}/history/{revision}/{f_path}',
1001 '/{repo_name}/history/{revision}/{f_path}',
1004 controller='files', action='history', revision='tip', f_path='',
1002 controller='files', action='history', revision='tip', f_path='',
1005 conditions={'function': check_repo},
1003 conditions={'function': check_repo},
1006 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1004 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1007
1005
1008 rmap.connect('files_authors_home',
1006 rmap.connect('files_authors_home',
1009 '/{repo_name}/authors/{revision}/{f_path}',
1007 '/{repo_name}/authors/{revision}/{f_path}',
1010 controller='files', action='authors', revision='tip', f_path='',
1008 controller='files', action='authors', revision='tip', f_path='',
1011 conditions={'function': check_repo},
1009 conditions={'function': check_repo},
1012 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1010 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1013
1011
1014 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
1012 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
1015 controller='files', action='diff', f_path='',
1013 controller='files', action='diff', f_path='',
1016 conditions={'function': check_repo},
1014 conditions={'function': check_repo},
1017 requirements=URL_NAME_REQUIREMENTS)
1015 requirements=URL_NAME_REQUIREMENTS)
1018
1016
1019 rmap.connect('files_diff_2way_home',
1017 rmap.connect('files_diff_2way_home',
1020 '/{repo_name}/diff-2way/{f_path}',
1018 '/{repo_name}/diff-2way/{f_path}',
1021 controller='files', action='diff_2way', f_path='',
1019 controller='files', action='diff_2way', f_path='',
1022 conditions={'function': check_repo},
1020 conditions={'function': check_repo},
1023 requirements=URL_NAME_REQUIREMENTS)
1021 requirements=URL_NAME_REQUIREMENTS)
1024
1022
1025 rmap.connect('files_rawfile_home',
1023 rmap.connect('files_rawfile_home',
1026 '/{repo_name}/rawfile/{revision}/{f_path}',
1024 '/{repo_name}/rawfile/{revision}/{f_path}',
1027 controller='files', action='rawfile', revision='tip',
1025 controller='files', action='rawfile', revision='tip',
1028 f_path='', conditions={'function': check_repo},
1026 f_path='', conditions={'function': check_repo},
1029 requirements=URL_NAME_REQUIREMENTS)
1027 requirements=URL_NAME_REQUIREMENTS)
1030
1028
1031 rmap.connect('files_raw_home',
1029 rmap.connect('files_raw_home',
1032 '/{repo_name}/raw/{revision}/{f_path}',
1030 '/{repo_name}/raw/{revision}/{f_path}',
1033 controller='files', action='raw', revision='tip', f_path='',
1031 controller='files', action='raw', revision='tip', f_path='',
1034 conditions={'function': check_repo},
1032 conditions={'function': check_repo},
1035 requirements=URL_NAME_REQUIREMENTS)
1033 requirements=URL_NAME_REQUIREMENTS)
1036
1034
1037 rmap.connect('files_render_home',
1035 rmap.connect('files_render_home',
1038 '/{repo_name}/render/{revision}/{f_path}',
1036 '/{repo_name}/render/{revision}/{f_path}',
1039 controller='files', action='index', revision='tip', f_path='',
1037 controller='files', action='index', revision='tip', f_path='',
1040 rendered=True, conditions={'function': check_repo},
1038 rendered=True, conditions={'function': check_repo},
1041 requirements=URL_NAME_REQUIREMENTS)
1039 requirements=URL_NAME_REQUIREMENTS)
1042
1040
1043 rmap.connect('files_annotate_home',
1041 rmap.connect('files_annotate_home',
1044 '/{repo_name}/annotate/{revision}/{f_path}',
1042 '/{repo_name}/annotate/{revision}/{f_path}',
1045 controller='files', action='index', revision='tip',
1043 controller='files', action='index', revision='tip',
1046 f_path='', annotate=True, conditions={'function': check_repo},
1044 f_path='', annotate=True, conditions={'function': check_repo},
1047 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1045 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1048
1046
1049 rmap.connect('files_annotate_previous',
1047 rmap.connect('files_annotate_previous',
1050 '/{repo_name}/annotate-previous/{revision}/{f_path}',
1048 '/{repo_name}/annotate-previous/{revision}/{f_path}',
1051 controller='files', action='annotate_previous', revision='tip',
1049 controller='files', action='annotate_previous', revision='tip',
1052 f_path='', annotate=True, conditions={'function': check_repo},
1050 f_path='', annotate=True, conditions={'function': check_repo},
1053 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1051 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1054
1052
1055 rmap.connect('files_edit',
1053 rmap.connect('files_edit',
1056 '/{repo_name}/edit/{revision}/{f_path}',
1054 '/{repo_name}/edit/{revision}/{f_path}',
1057 controller='files', action='edit', revision='tip',
1055 controller='files', action='edit', revision='tip',
1058 f_path='',
1056 f_path='',
1059 conditions={'function': check_repo, 'method': ['POST']},
1057 conditions={'function': check_repo, 'method': ['POST']},
1060 requirements=URL_NAME_REQUIREMENTS)
1058 requirements=URL_NAME_REQUIREMENTS)
1061
1059
1062 rmap.connect('files_edit_home',
1060 rmap.connect('files_edit_home',
1063 '/{repo_name}/edit/{revision}/{f_path}',
1061 '/{repo_name}/edit/{revision}/{f_path}',
1064 controller='files', action='edit_home', revision='tip',
1062 controller='files', action='edit_home', revision='tip',
1065 f_path='', conditions={'function': check_repo},
1063 f_path='', conditions={'function': check_repo},
1066 requirements=URL_NAME_REQUIREMENTS)
1064 requirements=URL_NAME_REQUIREMENTS)
1067
1065
1068 rmap.connect('files_add',
1066 rmap.connect('files_add',
1069 '/{repo_name}/add/{revision}/{f_path}',
1067 '/{repo_name}/add/{revision}/{f_path}',
1070 controller='files', action='add', revision='tip',
1068 controller='files', action='add', revision='tip',
1071 f_path='',
1069 f_path='',
1072 conditions={'function': check_repo, 'method': ['POST']},
1070 conditions={'function': check_repo, 'method': ['POST']},
1073 requirements=URL_NAME_REQUIREMENTS)
1071 requirements=URL_NAME_REQUIREMENTS)
1074
1072
1075 rmap.connect('files_add_home',
1073 rmap.connect('files_add_home',
1076 '/{repo_name}/add/{revision}/{f_path}',
1074 '/{repo_name}/add/{revision}/{f_path}',
1077 controller='files', action='add_home', revision='tip',
1075 controller='files', action='add_home', revision='tip',
1078 f_path='', conditions={'function': check_repo},
1076 f_path='', conditions={'function': check_repo},
1079 requirements=URL_NAME_REQUIREMENTS)
1077 requirements=URL_NAME_REQUIREMENTS)
1080
1078
1081 rmap.connect('files_delete',
1079 rmap.connect('files_delete',
1082 '/{repo_name}/delete/{revision}/{f_path}',
1080 '/{repo_name}/delete/{revision}/{f_path}',
1083 controller='files', action='delete', revision='tip',
1081 controller='files', action='delete', revision='tip',
1084 f_path='',
1082 f_path='',
1085 conditions={'function': check_repo, 'method': ['POST']},
1083 conditions={'function': check_repo, 'method': ['POST']},
1086 requirements=URL_NAME_REQUIREMENTS)
1084 requirements=URL_NAME_REQUIREMENTS)
1087
1085
1088 rmap.connect('files_delete_home',
1086 rmap.connect('files_delete_home',
1089 '/{repo_name}/delete/{revision}/{f_path}',
1087 '/{repo_name}/delete/{revision}/{f_path}',
1090 controller='files', action='delete_home', revision='tip',
1088 controller='files', action='delete_home', revision='tip',
1091 f_path='', conditions={'function': check_repo},
1089 f_path='', conditions={'function': check_repo},
1092 requirements=URL_NAME_REQUIREMENTS)
1090 requirements=URL_NAME_REQUIREMENTS)
1093
1091
1094 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
1092 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
1095 controller='files', action='archivefile',
1093 controller='files', action='archivefile',
1096 conditions={'function': check_repo},
1094 conditions={'function': check_repo},
1097 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1095 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1098
1096
1099 rmap.connect('files_nodelist_home',
1097 rmap.connect('files_nodelist_home',
1100 '/{repo_name}/nodelist/{revision}/{f_path}',
1098 '/{repo_name}/nodelist/{revision}/{f_path}',
1101 controller='files', action='nodelist',
1099 controller='files', action='nodelist',
1102 conditions={'function': check_repo},
1100 conditions={'function': check_repo},
1103 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1101 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1104
1102
1105 rmap.connect('files_nodetree_full',
1103 rmap.connect('files_nodetree_full',
1106 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
1104 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
1107 controller='files', action='nodetree_full',
1105 controller='files', action='nodetree_full',
1108 conditions={'function': check_repo},
1106 conditions={'function': check_repo},
1109 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1107 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1110
1108
1111 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
1109 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
1112 controller='forks', action='fork_create',
1110 controller='forks', action='fork_create',
1113 conditions={'function': check_repo, 'method': ['POST']},
1111 conditions={'function': check_repo, 'method': ['POST']},
1114 requirements=URL_NAME_REQUIREMENTS)
1112 requirements=URL_NAME_REQUIREMENTS)
1115
1113
1116 rmap.connect('repo_fork_home', '/{repo_name}/fork',
1114 rmap.connect('repo_fork_home', '/{repo_name}/fork',
1117 controller='forks', action='fork',
1115 controller='forks', action='fork',
1118 conditions={'function': check_repo},
1116 conditions={'function': check_repo},
1119 requirements=URL_NAME_REQUIREMENTS)
1117 requirements=URL_NAME_REQUIREMENTS)
1120
1118
1121 rmap.connect('repo_forks_home', '/{repo_name}/forks',
1119 rmap.connect('repo_forks_home', '/{repo_name}/forks',
1122 controller='forks', action='forks',
1120 controller='forks', action='forks',
1123 conditions={'function': check_repo},
1121 conditions={'function': check_repo},
1124 requirements=URL_NAME_REQUIREMENTS)
1122 requirements=URL_NAME_REQUIREMENTS)
1125
1123
1126 # must be here for proper group/repo catching pattern
1124 # must be here for proper group/repo catching pattern
1127 _connect_with_slash(
1125 _connect_with_slash(
1128 rmap, 'repo_group_home', '/{group_name}',
1126 rmap, 'repo_group_home', '/{group_name}',
1129 controller='home', action='index_repo_group',
1127 controller='home', action='index_repo_group',
1130 conditions={'function': check_group},
1128 conditions={'function': check_group},
1131 requirements=URL_NAME_REQUIREMENTS)
1129 requirements=URL_NAME_REQUIREMENTS)
1132
1130
1133 # catch all, at the end
1131 # catch all, at the end
1134 _connect_with_slash(
1132 _connect_with_slash(
1135 rmap, 'summary_home', '/{repo_name}', jsroute=True,
1133 rmap, 'summary_home', '/{repo_name}', jsroute=True,
1136 controller='summary', action='index',
1134 controller='summary', action='index',
1137 conditions={'function': check_repo},
1135 conditions={'function': check_repo},
1138 requirements=URL_NAME_REQUIREMENTS)
1136 requirements=URL_NAME_REQUIREMENTS)
1139
1137
1140 return rmap
1138 return rmap
1141
1139
1142
1140
1143 def _connect_with_slash(mapper, name, path, *args, **kwargs):
1141 def _connect_with_slash(mapper, name, path, *args, **kwargs):
1144 """
1142 """
1145 Connect a route with an optional trailing slash in `path`.
1143 Connect a route with an optional trailing slash in `path`.
1146 """
1144 """
1147 mapper.connect(name + '_slash', path + '/', *args, **kwargs)
1145 mapper.connect(name + '_slash', path + '/', *args, **kwargs)
1148 mapper.connect(name, path, *args, **kwargs)
1146 mapper.connect(name, path, *args, **kwargs)
@@ -1,257 +1,235 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Home controller for RhodeCode Enterprise
22 Home controller for RhodeCode Enterprise
23 """
23 """
24
24
25 import logging
25 import logging
26 import time
26 import time
27 import re
27 import re
28
28
29 from pylons import tmpl_context as c, request, url, config
29 from pylons import tmpl_context as c, request, url, config
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31 from sqlalchemy.sql import func
31 from sqlalchemy.sql import func
32
32
33 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
34 LoginRequired, HasPermissionAllDecorator, AuthUser,
34 LoginRequired, HasPermissionAllDecorator, AuthUser,
35 HasRepoGroupPermissionAnyDecorator, XHRRequired)
35 HasRepoGroupPermissionAnyDecorator, XHRRequired)
36 from rhodecode.lib.base import BaseController, render
36 from rhodecode.lib.base import BaseController, render
37 from rhodecode.lib.index import searcher_from_config
37 from rhodecode.lib.index import searcher_from_config
38 from rhodecode.lib.ext_json import json
38 from rhodecode.lib.ext_json import json
39 from rhodecode.lib.utils import jsonify
39 from rhodecode.lib.utils import jsonify
40 from rhodecode.lib.utils2 import safe_unicode, str2bool
40 from rhodecode.lib.utils2 import safe_unicode, str2bool
41 from rhodecode.model.db import Repository, RepoGroup
41 from rhodecode.model.db import Repository, RepoGroup
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
43 from rhodecode.model.repo_group import RepoGroupModel
43 from rhodecode.model.repo_group import RepoGroupModel
44 from rhodecode.model.scm import RepoList, RepoGroupList
44 from rhodecode.model.scm import RepoList, RepoGroupList
45
45
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class HomeController(BaseController):
50 class HomeController(BaseController):
51 def __before__(self):
51 def __before__(self):
52 super(HomeController, self).__before__()
52 super(HomeController, self).__before__()
53
53
54 def ping(self):
54 def ping(self):
55 """
55 """
56 Ping, doesn't require login, good for checking out the platform
56 Ping, doesn't require login, good for checking out the platform
57 """
57 """
58 instance_id = getattr(c, 'rhodecode_instanceid', '')
58 instance_id = getattr(c, 'rhodecode_instanceid', '')
59 return 'pong[%s] => %s' % (instance_id, self.ip_addr,)
59 return 'pong[%s] => %s' % (instance_id, self.ip_addr,)
60
60
61 @LoginRequired()
61 @LoginRequired()
62 @HasPermissionAllDecorator('hg.admin')
62 @HasPermissionAllDecorator('hg.admin')
63 def error_test(self):
63 def error_test(self):
64 """
64 """
65 Test exception handling and emails on errors
65 Test exception handling and emails on errors
66 """
66 """
67 class TestException(Exception):
67 class TestException(Exception):
68 pass
68 pass
69
69
70 msg = ('RhodeCode Enterprise %s test exception. Generation time: %s'
70 msg = ('RhodeCode Enterprise %s test exception. Generation time: %s'
71 % (c.rhodecode_name, time.time()))
71 % (c.rhodecode_name, time.time()))
72 raise TestException(msg)
72 raise TestException(msg)
73
73
74 def _get_groups_and_repos(self, repo_group_id=None):
74 def _get_groups_and_repos(self, repo_group_id=None):
75 # repo groups groups
75 # repo groups groups
76 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
76 repo_group_list = RepoGroup.get_all_repo_groups(group_id=repo_group_id)
77 _perms = ['group.read', 'group.write', 'group.admin']
77 _perms = ['group.read', 'group.write', 'group.admin']
78 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
78 repo_group_list_acl = RepoGroupList(repo_group_list, perm_set=_perms)
79 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
79 repo_group_data = RepoGroupModel().get_repo_groups_as_dict(
80 repo_group_list=repo_group_list_acl, admin=False)
80 repo_group_list=repo_group_list_acl, admin=False)
81
81
82 # repositories
82 # repositories
83 repo_list = Repository.get_all_repos(group_id=repo_group_id)
83 repo_list = Repository.get_all_repos(group_id=repo_group_id)
84 _perms = ['repository.read', 'repository.write', 'repository.admin']
84 _perms = ['repository.read', 'repository.write', 'repository.admin']
85 repo_list_acl = RepoList(repo_list, perm_set=_perms)
85 repo_list_acl = RepoList(repo_list, perm_set=_perms)
86 repo_data = RepoModel().get_repos_as_dict(
86 repo_data = RepoModel().get_repos_as_dict(
87 repo_list=repo_list_acl, admin=False)
87 repo_list=repo_list_acl, admin=False)
88
88
89 return repo_data, repo_group_data
89 return repo_data, repo_group_data
90
90
91 @LoginRequired()
91 @LoginRequired()
92 def index(self):
92 def index(self):
93 c.repo_group = None
93 c.repo_group = None
94
94
95 repo_data, repo_group_data = self._get_groups_and_repos()
95 repo_data, repo_group_data = self._get_groups_and_repos()
96 # json used to render the grids
96 # json used to render the grids
97 c.repos_data = json.dumps(repo_data)
97 c.repos_data = json.dumps(repo_data)
98 c.repo_groups_data = json.dumps(repo_group_data)
98 c.repo_groups_data = json.dumps(repo_group_data)
99
99
100 return render('/index.mako')
100 return render('/index.mako')
101
101
102 @LoginRequired()
102 @LoginRequired()
103 @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write',
103 @HasRepoGroupPermissionAnyDecorator('group.read', 'group.write',
104 'group.admin')
104 'group.admin')
105 def index_repo_group(self, group_name):
105 def index_repo_group(self, group_name):
106 """GET /repo_group_name: Show a specific item"""
106 """GET /repo_group_name: Show a specific item"""
107 c.repo_group = RepoGroupModel()._get_repo_group(group_name)
107 c.repo_group = RepoGroupModel()._get_repo_group(group_name)
108 repo_data, repo_group_data = self._get_groups_and_repos(
108 repo_data, repo_group_data = self._get_groups_and_repos(
109 c.repo_group.group_id)
109 c.repo_group.group_id)
110
110
111 # json used to render the grids
111 # json used to render the grids
112 c.repos_data = json.dumps(repo_data)
112 c.repos_data = json.dumps(repo_data)
113 c.repo_groups_data = json.dumps(repo_group_data)
113 c.repo_groups_data = json.dumps(repo_group_data)
114
114
115 return render('index_repo_group.mako')
115 return render('index_repo_group.mako')
116
116
117 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
117 def _get_repo_list(self, name_contains=None, repo_type=None, limit=20):
118 query = Repository.query()\
118 query = Repository.query()\
119 .order_by(func.length(Repository.repo_name))\
119 .order_by(func.length(Repository.repo_name))\
120 .order_by(Repository.repo_name)
120 .order_by(Repository.repo_name)
121
121
122 if repo_type:
122 if repo_type:
123 query = query.filter(Repository.repo_type == repo_type)
123 query = query.filter(Repository.repo_type == repo_type)
124
124
125 if name_contains:
125 if name_contains:
126 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
126 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
127 query = query.filter(
127 query = query.filter(
128 Repository.repo_name.ilike(ilike_expression))
128 Repository.repo_name.ilike(ilike_expression))
129 query = query.limit(limit)
129 query = query.limit(limit)
130
130
131 all_repos = query.all()
131 all_repos = query.all()
132 repo_iter = self.scm_model.get_repos(all_repos)
132 repo_iter = self.scm_model.get_repos(all_repos)
133 return [
133 return [
134 {
134 {
135 'id': obj['name'],
135 'id': obj['name'],
136 'text': obj['name'],
136 'text': obj['name'],
137 'type': 'repo',
137 'type': 'repo',
138 'obj': obj['dbrepo'],
138 'obj': obj['dbrepo'],
139 'url': url('summary_home', repo_name=obj['name'])
139 'url': url('summary_home', repo_name=obj['name'])
140 }
140 }
141 for obj in repo_iter]
141 for obj in repo_iter]
142
142
143 def _get_repo_group_list(self, name_contains=None, limit=20):
143 def _get_repo_group_list(self, name_contains=None, limit=20):
144 query = RepoGroup.query()\
144 query = RepoGroup.query()\
145 .order_by(func.length(RepoGroup.group_name))\
145 .order_by(func.length(RepoGroup.group_name))\
146 .order_by(RepoGroup.group_name)
146 .order_by(RepoGroup.group_name)
147
147
148 if name_contains:
148 if name_contains:
149 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
149 ilike_expression = u'%{}%'.format(safe_unicode(name_contains))
150 query = query.filter(
150 query = query.filter(
151 RepoGroup.group_name.ilike(ilike_expression))
151 RepoGroup.group_name.ilike(ilike_expression))
152 query = query.limit(limit)
152 query = query.limit(limit)
153
153
154 all_groups = query.all()
154 all_groups = query.all()
155 repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
155 repo_groups_iter = self.scm_model.get_repo_groups(all_groups)
156 return [
156 return [
157 {
157 {
158 'id': obj.group_name,
158 'id': obj.group_name,
159 'text': obj.group_name,
159 'text': obj.group_name,
160 'type': 'group',
160 'type': 'group',
161 'obj': {},
161 'obj': {},
162 'url': url('repo_group_home', group_name=obj.group_name)
162 'url': url('repo_group_home', group_name=obj.group_name)
163 }
163 }
164 for obj in repo_groups_iter]
164 for obj in repo_groups_iter]
165
165
166 def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
166 def _get_hash_commit_list(self, hash_starts_with=None, limit=20):
167 if not hash_starts_with or len(hash_starts_with) < 3:
167 if not hash_starts_with or len(hash_starts_with) < 3:
168 return []
168 return []
169
169
170 commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
170 commit_hashes = re.compile('([0-9a-f]{2,40})').findall(hash_starts_with)
171
171
172 if len(commit_hashes) != 1:
172 if len(commit_hashes) != 1:
173 return []
173 return []
174
174
175 commit_hash_prefix = commit_hashes[0]
175 commit_hash_prefix = commit_hashes[0]
176
176
177 auth_user = AuthUser(
177 auth_user = AuthUser(
178 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
178 user_id=c.rhodecode_user.user_id, ip_addr=self.ip_addr)
179 searcher = searcher_from_config(config)
179 searcher = searcher_from_config(config)
180 result = searcher.search(
180 result = searcher.search(
181 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user,
181 'commit_id:%s*' % commit_hash_prefix, 'commit', auth_user,
182 raise_on_exc=False)
182 raise_on_exc=False)
183
183
184 return [
184 return [
185 {
185 {
186 'id': entry['commit_id'],
186 'id': entry['commit_id'],
187 'text': entry['commit_id'],
187 'text': entry['commit_id'],
188 'type': 'commit',
188 'type': 'commit',
189 'obj': {'repo': entry['repository']},
189 'obj': {'repo': entry['repository']},
190 'url': url('changeset_home',
190 'url': url('changeset_home',
191 repo_name=entry['repository'],
191 repo_name=entry['repository'],
192 revision=entry['commit_id'])
192 revision=entry['commit_id'])
193 }
193 }
194 for entry in result['results']]
194 for entry in result['results']]
195
195
196 @LoginRequired()
196 @LoginRequired()
197 @XHRRequired()
197 @XHRRequired()
198 @jsonify
198 @jsonify
199 def goto_switcher_data(self):
199 def goto_switcher_data(self):
200 query = request.GET.get('query')
200 query = request.GET.get('query')
201 log.debug('generating goto switcher list, query %s', query)
201 log.debug('generating goto switcher list, query %s', query)
202
202
203 res = []
203 res = []
204 repo_groups = self._get_repo_group_list(query)
204 repo_groups = self._get_repo_group_list(query)
205 if repo_groups:
205 if repo_groups:
206 res.append({
206 res.append({
207 'text': _('Groups'),
207 'text': _('Groups'),
208 'children': repo_groups
208 'children': repo_groups
209 })
209 })
210
210
211 repos = self._get_repo_list(query)
211 repos = self._get_repo_list(query)
212 if repos:
212 if repos:
213 res.append({
213 res.append({
214 'text': _('Repositories'),
214 'text': _('Repositories'),
215 'children': repos
215 'children': repos
216 })
216 })
217
217
218 commits = self._get_hash_commit_list(query)
218 commits = self._get_hash_commit_list(query)
219 if commits:
219 if commits:
220 unique_repos = {}
220 unique_repos = {}
221 for commit in commits:
221 for commit in commits:
222 unique_repos.setdefault(commit['obj']['repo'], []
222 unique_repos.setdefault(commit['obj']['repo'], []
223 ).append(commit)
223 ).append(commit)
224
224
225 for repo in unique_repos:
225 for repo in unique_repos:
226 res.append({
226 res.append({
227 'text': _('Commits in %(repo)s') % {'repo': repo},
227 'text': _('Commits in %(repo)s') % {'repo': repo},
228 'children': unique_repos[repo]
228 'children': unique_repos[repo]
229 })
229 })
230
230
231 data = {
231 data = {
232 'more': False,
232 'more': False,
233 'results': res
233 'results': res
234 }
234 }
235 return data
235 return data
236
237 @LoginRequired()
238 @XHRRequired()
239 @jsonify
240 def repo_list_data(self):
241 query = request.GET.get('query')
242 repo_type = request.GET.get('repo_type')
243 log.debug('generating repo list, query:%s', query)
244
245 res = []
246 repos = self._get_repo_list(query, repo_type=repo_type)
247 if repos:
248 res.append({
249 'text': _('Repositories'),
250 'children': repos
251 })
252
253 data = {
254 'more': False,
255 'results': res
256 }
257 return data
@@ -1,111 +1,112 b''
1
1
2 /******************************************************************************
2 /******************************************************************************
3 * *
3 * *
4 * DO NOT CHANGE THIS FILE MANUALLY *
4 * DO NOT CHANGE THIS FILE MANUALLY *
5 * *
5 * *
6 * *
6 * *
7 * This file is automatically generated when the app starts up with *
7 * This file is automatically generated when the app starts up with *
8 * generate_js_files = true *
8 * generate_js_files = true *
9 * *
9 * *
10 * To add a route here pass jsroute=True to the route definition in the app *
10 * To add a route here pass jsroute=True to the route definition in the app *
11 * *
11 * *
12 ******************************************************************************/
12 ******************************************************************************/
13 function registerRCRoutes() {
13 function registerRCRoutes() {
14 // routes registration
14 // routes registration
15 pyroutes.register('home', '/', []);
15 pyroutes.register('home', '/', []);
16 pyroutes.register('user_autocomplete_data', '/_users', []);
17 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
18 pyroutes.register('new_repo', '/_admin/create_repository', []);
16 pyroutes.register('new_repo', '/_admin/create_repository', []);
19 pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
17 pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
20 pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
18 pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
21 pyroutes.register('gists', '/_admin/gists', []);
19 pyroutes.register('gists', '/_admin/gists', []);
22 pyroutes.register('new_gist', '/_admin/gists/new', []);
20 pyroutes.register('new_gist', '/_admin/gists/new', []);
23 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
21 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
24 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
22 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
25 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
23 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
26 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
24 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
27 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']);
25 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']);
28 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
26 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
29 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
27 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
30 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
28 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
31 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
29 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
32 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
30 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
33 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
31 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
34 pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
32 pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
35 pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
33 pyroutes.register('compare_url', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
36 pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
34 pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
37 pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
35 pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
38 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
36 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
39 pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
37 pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
40 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
38 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
41 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
39 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
42 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
40 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
43 pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
41 pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
44 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
42 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
45 pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
43 pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
46 pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
44 pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
47 pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']);
45 pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']);
48 pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
46 pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
49 pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
47 pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
50 pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
48 pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
51 pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
49 pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
52 pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
50 pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
53 pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
51 pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
54 pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
52 pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
55 pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
53 pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
56 pyroutes.register('summary_home_slash', '/%(repo_name)s/', ['repo_name']);
54 pyroutes.register('summary_home_slash', '/%(repo_name)s/', ['repo_name']);
57 pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']);
55 pyroutes.register('summary_home', '/%(repo_name)s', ['repo_name']);
58 pyroutes.register('favicon', '/favicon.ico', []);
56 pyroutes.register('favicon', '/favicon.ico', []);
59 pyroutes.register('robots', '/robots.txt', []);
57 pyroutes.register('robots', '/robots.txt', []);
60 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
58 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
61 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
59 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
62 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
60 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
63 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
61 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
64 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
62 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
65 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
63 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
66 pyroutes.register('repo_group_integrations_home', '%(repo_group_name)s/settings/integrations', ['repo_group_name']);
64 pyroutes.register('repo_group_integrations_home', '%(repo_group_name)s/settings/integrations', ['repo_group_name']);
67 pyroutes.register('repo_group_integrations_list', '%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
65 pyroutes.register('repo_group_integrations_list', '%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
68 pyroutes.register('repo_group_integrations_new', '%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
66 pyroutes.register('repo_group_integrations_new', '%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
69 pyroutes.register('repo_group_integrations_create', '%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
67 pyroutes.register('repo_group_integrations_create', '%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
70 pyroutes.register('repo_group_integrations_edit', '%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
68 pyroutes.register('repo_group_integrations_edit', '%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
71 pyroutes.register('repo_integrations_home', '%(repo_name)s/settings/integrations', ['repo_name']);
69 pyroutes.register('repo_integrations_home', '%(repo_name)s/settings/integrations', ['repo_name']);
72 pyroutes.register('repo_integrations_list', '%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
70 pyroutes.register('repo_integrations_list', '%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
73 pyroutes.register('repo_integrations_new', '%(repo_name)s/settings/integrations/new', ['repo_name']);
71 pyroutes.register('repo_integrations_new', '%(repo_name)s/settings/integrations/new', ['repo_name']);
74 pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
72 pyroutes.register('repo_integrations_create', '%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
75 pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
73 pyroutes.register('repo_integrations_edit', '%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
76 pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []);
74 pyroutes.register('admin_settings_open_source', '_admin/settings/open_source', []);
77 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []);
75 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '_admin/settings/vcs/svn_generate_cfg', []);
78 pyroutes.register('admin_settings_system', '_admin/settings/system', []);
76 pyroutes.register('admin_settings_system', '_admin/settings/system', []);
79 pyroutes.register('admin_settings_system_update', '_admin/settings/system/updates', []);
77 pyroutes.register('admin_settings_system_update', '_admin/settings/system/updates', []);
80 pyroutes.register('admin_settings_sessions', '_admin/settings/sessions', []);
78 pyroutes.register('admin_settings_sessions', '_admin/settings/sessions', []);
81 pyroutes.register('admin_settings_sessions_cleanup', '_admin/settings/sessions/cleanup', []);
79 pyroutes.register('admin_settings_sessions_cleanup', '_admin/settings/sessions/cleanup', []);
82 pyroutes.register('users', '_admin/users', []);
80 pyroutes.register('users', '_admin/users', []);
83 pyroutes.register('users_data', '_admin/users_data', []);
81 pyroutes.register('users_data', '_admin/users_data', []);
84 pyroutes.register('edit_user_auth_tokens', '_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
82 pyroutes.register('edit_user_auth_tokens', '_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
85 pyroutes.register('edit_user_auth_tokens_add', '_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
83 pyroutes.register('edit_user_auth_tokens_add', '_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
86 pyroutes.register('edit_user_auth_tokens_delete', '_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
84 pyroutes.register('edit_user_auth_tokens_delete', '_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
87 pyroutes.register('edit_user_groups_management', '_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
85 pyroutes.register('edit_user_groups_management', '_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
88 pyroutes.register('edit_user_groups_management_updates', '_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
86 pyroutes.register('edit_user_groups_management_updates', '_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
89 pyroutes.register('edit_user_audit_logs', '_admin/users/%(user_id)s/edit/audit', ['user_id']);
87 pyroutes.register('edit_user_audit_logs', '_admin/users/%(user_id)s/edit/audit', ['user_id']);
90 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
88 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
91 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
89 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
92 pyroutes.register('channelstream_proxy', '/_channelstream', []);
90 pyroutes.register('channelstream_proxy', '/_channelstream', []);
93 pyroutes.register('login', '/_admin/login', []);
91 pyroutes.register('login', '/_admin/login', []);
94 pyroutes.register('logout', '/_admin/logout', []);
92 pyroutes.register('logout', '/_admin/logout', []);
95 pyroutes.register('register', '/_admin/register', []);
93 pyroutes.register('register', '/_admin/register', []);
96 pyroutes.register('reset_password', '/_admin/password_reset', []);
94 pyroutes.register('reset_password', '/_admin/password_reset', []);
97 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
95 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
96 pyroutes.register('user_autocomplete_data', '/_users', []);
97 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
98 pyroutes.register('repo_list_data', '/_repos', []);
98 pyroutes.register('repo_maintenance', '/%(repo_name)s/maintenance', ['repo_name']);
99 pyroutes.register('repo_maintenance', '/%(repo_name)s/maintenance', ['repo_name']);
99 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/maintenance/execute', ['repo_name']);
100 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/maintenance/execute', ['repo_name']);
100 pyroutes.register('strip', '/%(repo_name)s/strip', ['repo_name']);
101 pyroutes.register('strip', '/%(repo_name)s/strip', ['repo_name']);
101 pyroutes.register('strip_check', '/%(repo_name)s/strip_check', ['repo_name']);
102 pyroutes.register('strip_check', '/%(repo_name)s/strip_check', ['repo_name']);
102 pyroutes.register('strip_execute', '/%(repo_name)s/strip_execute', ['repo_name']);
103 pyroutes.register('strip_execute', '/%(repo_name)s/strip_execute', ['repo_name']);
103 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
104 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
104 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
105 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
105 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
106 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
106 pyroutes.register('my_account_password_update', '/_admin/my_account/password', []);
107 pyroutes.register('my_account_password_update', '/_admin/my_account/password', []);
107 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
108 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
108 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
109 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
109 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
110 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
110 pyroutes.register('apiv2', '/_admin/api', []);
111 pyroutes.register('apiv2', '/_admin/api', []);
111 }
112 }
@@ -1,160 +1,160 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Authentication Tokens')}</h3>
3 <h3 class="panel-title">${_('Authentication Tokens')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 <div class="apikeys_wrap">
6 <div class="apikeys_wrap">
7 <p>
7 <p>
8 ${_('Each token can have a role. Token with a role can be used only in given context, '
8 ${_('Each token can have a role. Token with a role can be used only in given context, '
9 'e.g. VCS tokens can be used together with the authtoken auth plugin for git/hg/svn operations only.')}
9 'e.g. VCS tokens can be used together with the authtoken auth plugin for git/hg/svn operations only.')}
10 </p>
10 </p>
11 <table class="rctable auth_tokens">
11 <table class="rctable auth_tokens">
12 <tr>
12 <tr>
13 <th>${_('Token')}</th>
13 <th>${_('Token')}</th>
14 <th>${_('Scope')}</th>
14 <th>${_('Scope')}</th>
15 <th>${_('Description')}</th>
15 <th>${_('Description')}</th>
16 <th>${_('Role')}</th>
16 <th>${_('Role')}</th>
17 <th>${_('Expiration')}</th>
17 <th>${_('Expiration')}</th>
18 <th>${_('Action')}</th>
18 <th>${_('Action')}</th>
19 </tr>
19 </tr>
20 %if c.user_auth_tokens:
20 %if c.user_auth_tokens:
21 %for auth_token in c.user_auth_tokens:
21 %for auth_token in c.user_auth_tokens:
22 <tr class="${'expired' if auth_token.expired else ''}">
22 <tr class="${'expired' if auth_token.expired else ''}">
23 <td class="truncate-wrap td-authtoken">
23 <td class="truncate-wrap td-authtoken">
24 <div class="user_auth_tokens truncate autoexpand">
24 <div class="user_auth_tokens truncate autoexpand">
25 <code>${auth_token.api_key}</code>
25 <code>${auth_token.api_key}</code>
26 </div>
26 </div>
27 </td>
27 </td>
28 <td class="td">${auth_token.scope_humanized}</td>
28 <td class="td">${auth_token.scope_humanized}</td>
29 <td class="td-wrap">${auth_token.description}</td>
29 <td class="td-wrap">${auth_token.description}</td>
30 <td class="td-tags">
30 <td class="td-tags">
31 <span class="tag disabled">${auth_token.role_humanized}</span>
31 <span class="tag disabled">${auth_token.role_humanized}</span>
32 </td>
32 </td>
33 <td class="td-exp">
33 <td class="td-exp">
34 %if auth_token.expires == -1:
34 %if auth_token.expires == -1:
35 ${_('never')}
35 ${_('never')}
36 %else:
36 %else:
37 %if auth_token.expired:
37 %if auth_token.expired:
38 <span style="text-decoration: line-through">${h.age_component(h.time_to_utcdatetime(auth_token.expires))}</span>
38 <span style="text-decoration: line-through">${h.age_component(h.time_to_utcdatetime(auth_token.expires))}</span>
39 %else:
39 %else:
40 ${h.age_component(h.time_to_utcdatetime(auth_token.expires))}
40 ${h.age_component(h.time_to_utcdatetime(auth_token.expires))}
41 %endif
41 %endif
42 %endif
42 %endif
43 </td>
43 </td>
44 <td class="td-action">
44 <td class="td-action">
45 ${h.secure_form(h.route_path('my_account_auth_tokens_delete'), method='post')}
45 ${h.secure_form(h.route_path('my_account_auth_tokens_delete'), method='post')}
46 ${h.hidden('del_auth_token',auth_token.api_key)}
46 ${h.hidden('del_auth_token',auth_token.api_key)}
47 <button class="btn btn-link btn-danger" type="submit"
47 <button class="btn btn-link btn-danger" type="submit"
48 onclick="return confirm('${_('Confirm to remove this auth token: %s') % auth_token.api_key}');">
48 onclick="return confirm('${_('Confirm to remove this auth token: %s') % auth_token.api_key}');">
49 ${_('Delete')}
49 ${_('Delete')}
50 </button>
50 </button>
51 ${h.end_form()}
51 ${h.end_form()}
52 </td>
52 </td>
53 </tr>
53 </tr>
54 %endfor
54 %endfor
55 %else:
55 %else:
56 <tr><td><div class="ip">${_('No additional auth tokens specified')}</div></td></tr>
56 <tr><td><div class="ip">${_('No additional auth tokens specified')}</div></td></tr>
57 %endif
57 %endif
58 </table>
58 </table>
59 </div>
59 </div>
60
60
61 <div class="user_auth_tokens">
61 <div class="user_auth_tokens">
62 ${h.secure_form(h.route_path('my_account_auth_tokens_add'), method='post')}
62 ${h.secure_form(h.route_path('my_account_auth_tokens_add'), method='post')}
63 <div class="form form-vertical">
63 <div class="form form-vertical">
64 <!-- fields -->
64 <!-- fields -->
65 <div class="fields">
65 <div class="fields">
66 <div class="field">
66 <div class="field">
67 <div class="label">
67 <div class="label">
68 <label for="new_email">${_('New authentication token')}:</label>
68 <label for="new_email">${_('New authentication token')}:</label>
69 </div>
69 </div>
70 <div class="input">
70 <div class="input">
71 ${h.text('description', class_='medium', placeholder=_('Description'))}
71 ${h.text('description', class_='medium', placeholder=_('Description'))}
72 ${h.select('lifetime', '', c.lifetime_options)}
72 ${h.select('lifetime', '', c.lifetime_options)}
73 ${h.select('role', '', c.role_options)}
73 ${h.select('role', '', c.role_options)}
74
74
75 % if c.allow_scoped_tokens:
75 % if c.allow_scoped_tokens:
76 ${h.hidden('scope_repo_id')}
76 ${h.hidden('scope_repo_id')}
77 % else:
77 % else:
78 ${h.select('scope_repo_id_disabled', '', ['Scopes available in EE edition'], disabled='disabled')}
78 ${h.select('scope_repo_id_disabled', '', ['Scopes available in EE edition'], disabled='disabled')}
79 % endif
79 % endif
80 </div>
80 </div>
81 <p class="help-block">
81 <p class="help-block">
82 ${_('Repository scope works only with tokens with VCS type.')}
82 ${_('Repository scope works only with tokens with VCS type.')}
83 </p>
83 </p>
84 </div>
84 </div>
85 <div class="buttons">
85 <div class="buttons">
86 ${h.submit('save',_('Add'),class_="btn")}
86 ${h.submit('save',_('Add'),class_="btn")}
87 ${h.reset('reset',_('Reset'),class_="btn")}
87 ${h.reset('reset',_('Reset'),class_="btn")}
88 </div>
88 </div>
89 </div>
89 </div>
90 </div>
90 </div>
91 ${h.end_form()}
91 ${h.end_form()}
92 </div>
92 </div>
93 </div>
93 </div>
94 </div>
94 </div>
95 <script>
95 <script>
96 $(document).ready(function(){
96 $(document).ready(function(){
97
97
98 var select2Options = {
98 var select2Options = {
99 'containerCssClass': "drop-menu",
99 'containerCssClass': "drop-menu",
100 'dropdownCssClass': "drop-menu-dropdown",
100 'dropdownCssClass': "drop-menu-dropdown",
101 'dropdownAutoWidth': true
101 'dropdownAutoWidth': true
102 };
102 };
103 $("#lifetime").select2(select2Options);
103 $("#lifetime").select2(select2Options);
104 $("#role").select2(select2Options);
104 $("#role").select2(select2Options);
105
105
106 var repoFilter = function(data) {
106 var repoFilter = function(data) {
107 var results = [];
107 var results = [];
108
108
109 if (!data.results[0]) {
109 if (!data.results[0]) {
110 return data
110 return data
111 }
111 }
112
112
113 $.each(data.results[0].children, function() {
113 $.each(data.results[0].children, function() {
114 // replace name to ID for submision
114 // replace name to ID for submision
115 this.id = this.obj.repo_id;
115 this.id = this.obj.repo_id;
116 results.push(this);
116 results.push(this);
117 });
117 });
118
118
119 data.results[0].children = results;
119 data.results[0].children = results;
120 return data;
120 return data;
121 };
121 };
122
122
123 $("#scope_repo_id_disabled").select2(select2Options);
123 $("#scope_repo_id_disabled").select2(select2Options);
124
124
125 $("#scope_repo_id").select2({
125 $("#scope_repo_id").select2({
126 cachedDataSource: {},
126 cachedDataSource: {},
127 minimumInputLength: 2,
127 minimumInputLength: 2,
128 placeholder: "${_('repository scope')}",
128 placeholder: "${_('repository scope')}",
129 dropdownAutoWidth: true,
129 dropdownAutoWidth: true,
130 containerCssClass: "drop-menu",
130 containerCssClass: "drop-menu",
131 dropdownCssClass: "drop-menu-dropdown",
131 dropdownCssClass: "drop-menu-dropdown",
132 formatResult: formatResult,
132 formatResult: formatResult,
133 query: $.debounce(250, function(query){
133 query: $.debounce(250, function(query){
134 self = this;
134 self = this;
135 var cacheKey = query.term;
135 var cacheKey = query.term;
136 var cachedData = self.cachedDataSource[cacheKey];
136 var cachedData = self.cachedDataSource[cacheKey];
137
137
138 if (cachedData) {
138 if (cachedData) {
139 query.callback({results: cachedData.results});
139 query.callback({results: cachedData.results});
140 } else {
140 } else {
141 $.ajax({
141 $.ajax({
142 url: "${h.url('repo_list_data')}",
142 url: pyroutes.url('repo_list_data'),
143 data: {'query': query.term},
143 data: {'query': query.term},
144 dataType: 'json',
144 dataType: 'json',
145 type: 'GET',
145 type: 'GET',
146 success: function(data) {
146 success: function(data) {
147 data = repoFilter(data);
147 data = repoFilter(data);
148 self.cachedDataSource[cacheKey] = data;
148 self.cachedDataSource[cacheKey] = data;
149 query.callback({results: data.results});
149 query.callback({results: data.results});
150 },
150 },
151 error: function(data, textStatus, errorThrown) {
151 error: function(data, textStatus, errorThrown) {
152 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
152 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
153 }
153 }
154 })
154 })
155 }
155 }
156 })
156 })
157 });
157 });
158
158
159 });
159 });
160 </script>
160 </script>
@@ -1,211 +1,211 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <%
3 <%
4 elems = [
4 elems = [
5 (_('Owner'), lambda:base.gravatar_with_user(c.repo_info.user.email), '', ''),
5 (_('Owner'), lambda:base.gravatar_with_user(c.repo_info.user.email), '', ''),
6 (_('Created on'), h.format_date(c.repo_info.created_on), '', ''),
6 (_('Created on'), h.format_date(c.repo_info.created_on), '', ''),
7 (_('Updated on'), h.format_date(c.repo_info.updated_on), '', ''),
7 (_('Updated on'), h.format_date(c.repo_info.updated_on), '', ''),
8 (_('Cached Commit id'), lambda: h.link_to(c.repo_info.changeset_cache.get('short_id'), h.url('changeset_home',repo_name=c.repo_name,revision=c.repo_info.changeset_cache.get('raw_id'))), '', ''),
8 (_('Cached Commit id'), lambda: h.link_to(c.repo_info.changeset_cache.get('short_id'), h.url('changeset_home',repo_name=c.repo_name,revision=c.repo_info.changeset_cache.get('raw_id'))), '', ''),
9 ]
9 ]
10 %>
10 %>
11
11
12 <div class="panel panel-default">
12 <div class="panel panel-default">
13 <div class="panel-heading">
13 <div class="panel-heading">
14 <h3 class="panel-title">${_('Repository: %s') % c.repo_info.repo_name}</h3>
14 <h3 class="panel-title">${_('Repository: %s') % c.repo_info.repo_name}</h3>
15 </div>
15 </div>
16 <div class="panel-body">
16 <div class="panel-body">
17 ${base.dt_info_panel(elems)}
17 ${base.dt_info_panel(elems)}
18 </div>
18 </div>
19 </div>
19 </div>
20
20
21
21
22 <div class="panel panel-default">
22 <div class="panel panel-default">
23 <div class="panel-heading">
23 <div class="panel-heading">
24 <h3 class="panel-title">${_('Fork Reference')}</h3>
24 <h3 class="panel-title">${_('Fork Reference')}</h3>
25 </div>
25 </div>
26 <div class="panel-body">
26 <div class="panel-body">
27 ${h.secure_form(url('edit_repo_advanced_fork', repo_name=c.repo_info.repo_name), method='put')}
27 ${h.secure_form(url('edit_repo_advanced_fork', repo_name=c.repo_info.repo_name), method='put')}
28
28
29 % if c.repo_info.fork:
29 % if c.repo_info.fork:
30 <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.repo_info.fork.repo_name, h.url('summary_home', repo_name=c.repo_info.fork.repo_name))})}
30 <div class="panel-body-title-text">${h.literal(_('This repository is a fork of %(repo_link)s') % {'repo_link': h.link_to_if(c.has_origin_repo_read_perm,c.repo_info.fork.repo_name, h.url('summary_home', repo_name=c.repo_info.fork.repo_name))})}
31 | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div>
31 | <button class="btn btn-link btn-danger" type="submit">Remove fork reference</button></div>
32 % endif
32 % endif
33
33
34 <div class="field">
34 <div class="field">
35 ${h.hidden('id_fork_of')}
35 ${h.hidden('id_fork_of')}
36 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small",)}
36 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('Set'),class_="btn btn-small",)}
37 </div>
37 </div>
38 <div class="field">
38 <div class="field">
39 <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span>
39 <span class="help-block">${_('Manually set this repository as a fork of another from the list')}</span>
40 </div>
40 </div>
41 ${h.end_form()}
41 ${h.end_form()}
42 </div>
42 </div>
43 </div>
43 </div>
44
44
45
45
46 <div class="panel panel-default">
46 <div class="panel panel-default">
47 <div class="panel-heading">
47 <div class="panel-heading">
48 <h3 class="panel-title">${_('Public Journal Visibility')}</h3>
48 <h3 class="panel-title">${_('Public Journal Visibility')}</h3>
49 </div>
49 </div>
50 <div class="panel-body">
50 <div class="panel-body">
51 ${h.secure_form(url('edit_repo_advanced_journal', repo_name=c.repo_info.repo_name), method='put')}
51 ${h.secure_form(url('edit_repo_advanced_journal', repo_name=c.repo_info.repo_name), method='put')}
52 <div class="field">
52 <div class="field">
53 %if c.in_public_journal:
53 %if c.in_public_journal:
54 <button class="btn btn-small" type="submit">
54 <button class="btn btn-small" type="submit">
55 <i class="icon-minus"></i>
55 <i class="icon-minus"></i>
56 ${_('Remove from Public Journal')}
56 ${_('Remove from Public Journal')}
57 </button>
57 </button>
58 %else:
58 %else:
59 <button class="btn btn-small" type="submit">
59 <button class="btn btn-small" type="submit">
60 ${_('Add to Public Journal')}
60 ${_('Add to Public Journal')}
61 </button>
61 </button>
62 %endif
62 %endif
63 </div>
63 </div>
64 <div class="field" >
64 <div class="field" >
65 <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span>
65 <span class="help-block">${_('All actions made on this repository will be visible to everyone following the public journal.')}</span>
66 </div>
66 </div>
67 ${h.end_form()}
67 ${h.end_form()}
68 </div>
68 </div>
69 </div>
69 </div>
70
70
71
71
72 <div class="panel panel-default">
72 <div class="panel panel-default">
73 <div class="panel-heading">
73 <div class="panel-heading">
74 <h3 class="panel-title">${_('Locking state')}</h3>
74 <h3 class="panel-title">${_('Locking state')}</h3>
75 </div>
75 </div>
76 <div class="panel-body">
76 <div class="panel-body">
77 ${h.secure_form(url('edit_repo_advanced_locking', repo_name=c.repo_info.repo_name), method='put')}
77 ${h.secure_form(url('edit_repo_advanced_locking', repo_name=c.repo_info.repo_name), method='put')}
78
78
79 %if c.repo_info.locked[0]:
79 %if c.repo_info.locked[0]:
80 <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.repo_info.locked[0]),
80 <div class="panel-body-title-text">${'Locked by %s on %s. Lock reason: %s' % (h.person_by_id(c.repo_info.locked[0]),
81 h.format_date(h. time_to_datetime(c.repo_info.locked[1])), c.repo_info.locked[2])}</div>
81 h.format_date(h. time_to_datetime(c.repo_info.locked[1])), c.repo_info.locked[2])}</div>
82 %else:
82 %else:
83 <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div>
83 <div class="panel-body-title-text">${_('This Repository is not currently locked.')}</div>
84 %endif
84 %endif
85
85
86 <div class="field" >
86 <div class="field" >
87 %if c.repo_info.locked[0]:
87 %if c.repo_info.locked[0]:
88 ${h.hidden('set_unlock', '1')}
88 ${h.hidden('set_unlock', '1')}
89 <button class="btn btn-small" type="submit"
89 <button class="btn btn-small" type="submit"
90 onclick="return confirm('${_('Confirm to unlock repository.')}');">
90 onclick="return confirm('${_('Confirm to unlock repository.')}');">
91 <i class="icon-unlock"></i>
91 <i class="icon-unlock"></i>
92 ${_('Unlock repository')}
92 ${_('Unlock repository')}
93 </button>
93 </button>
94 %else:
94 %else:
95 ${h.hidden('set_lock', '1')}
95 ${h.hidden('set_lock', '1')}
96 <button class="btn btn-small" type="submit"
96 <button class="btn btn-small" type="submit"
97 onclick="return confirm('${_('Confirm to lock repository.')}');">
97 onclick="return confirm('${_('Confirm to lock repository.')}');">
98 <i class="icon-lock"></i>
98 <i class="icon-lock"></i>
99 ${_('Lock Repository')}
99 ${_('Lock Repository')}
100 </button>
100 </button>
101 %endif
101 %endif
102 </div>
102 </div>
103 <div class="field" >
103 <div class="field" >
104 <span class="help-block">
104 <span class="help-block">
105 ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')}
105 ${_('Force repository locking. This only works when anonymous access is disabled. Pulling from the repository locks the repository to that user until the same user pushes to that repository again.')}
106 </span>
106 </span>
107 </div>
107 </div>
108 ${h.end_form()}
108 ${h.end_form()}
109 </div>
109 </div>
110 </div>
110 </div>
111
111
112 <div class="panel panel-danger">
112 <div class="panel panel-danger">
113 <div class="panel-heading">
113 <div class="panel-heading">
114 <h3 class="panel-title">${_('Delete repository')}</h3>
114 <h3 class="panel-title">${_('Delete repository')}</h3>
115 </div>
115 </div>
116 <div class="panel-body">
116 <div class="panel-body">
117 ${h.secure_form(url('repo', repo_name=c.repo_name),method='delete')}
117 ${h.secure_form(url('repo', repo_name=c.repo_name),method='delete')}
118 <table class="display">
118 <table class="display">
119 <tr>
119 <tr>
120 <td>
120 <td>
121 ${ungettext('This repository has %s fork.', 'This repository has %s forks.', c.repo_info. forks.count()) % c.repo_info.forks.count()}
121 ${ungettext('This repository has %s fork.', 'This repository has %s forks.', c.repo_info. forks.count()) % c.repo_info.forks.count()}
122 </td>
122 </td>
123 <td>
123 <td>
124 %if c.repo_info.forks.count():
124 %if c.repo_info.forks.count():
125 <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label>
125 <input type="radio" name="forks" value="detach_forks" checked="checked"/> <label for="forks">${_('Detach forks')}</label>
126 %endif
126 %endif
127 </td>
127 </td>
128 <td>
128 <td>
129 %if c.repo_info.forks.count():
129 %if c.repo_info.forks.count():
130 <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label>
130 <input type="radio" name="forks" value="delete_forks"/> <label for="forks">${_('Delete forks')}</label>
131 %endif
131 %endif
132 </td>
132 </td>
133 </tr>
133 </tr>
134 </table>
134 </table>
135 <div style="margin: 0 0 20px 0" class="fake-space"></div>
135 <div style="margin: 0 0 20px 0" class="fake-space"></div>
136
136
137 <div class="field">
137 <div class="field">
138 <button class="btn btn-small btn-danger" type="submit"
138 <button class="btn btn-small btn-danger" type="submit"
139 onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');">
139 onclick="return confirm('${_('Confirm to delete this repository: %s') % c.repo_name}');">
140 <i class="icon-remove-sign"></i>
140 <i class="icon-remove-sign"></i>
141 ${_('Delete This Repository')}
141 ${_('Delete This Repository')}
142 </button>
142 </button>
143 </div>
143 </div>
144 <div class="field">
144 <div class="field">
145 <span class="help-block">
145 <span class="help-block">
146 ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command.')}
146 ${_('This repository will be renamed in a special way in order to make it inaccessible to RhodeCode Enterprise and its VCS systems. If you need to fully delete it from the file system, please do it manually, or with rhodecode-cleanup-repos command.')}
147 </span>
147 </span>
148 </div>
148 </div>
149
149
150 ${h.end_form()}
150 ${h.end_form()}
151 </div>
151 </div>
152 </div>
152 </div>
153
153
154
154
155 <script>
155 <script>
156
156
157 var currentRepoId = ${c.repo_info.repo_id};
157 var currentRepoId = ${c.repo_info.repo_id};
158
158
159 var repoTypeFilter = function(data) {
159 var repoTypeFilter = function(data) {
160 var results = [];
160 var results = [];
161
161
162 if (!data.results[0]) {
162 if (!data.results[0]) {
163 return data
163 return data
164 }
164 }
165
165
166 $.each(data.results[0].children, function() {
166 $.each(data.results[0].children, function() {
167 // filter out the SAME repo, it cannot be used as fork of itself
167 // filter out the SAME repo, it cannot be used as fork of itself
168 if (this.obj.repo_id != currentRepoId) {
168 if (this.obj.repo_id != currentRepoId) {
169 this.id = this.obj.repo_id;
169 this.id = this.obj.repo_id;
170 results.push(this)
170 results.push(this)
171 }
171 }
172 });
172 });
173 data.results[0].children = results;
173 data.results[0].children = results;
174 return data;
174 return data;
175 };
175 };
176
176
177 $("#id_fork_of").select2({
177 $("#id_fork_of").select2({
178 cachedDataSource: {},
178 cachedDataSource: {},
179 minimumInputLength: 2,
179 minimumInputLength: 2,
180 placeholder: "${_('Change repository') if c.repo_info.fork else _('Pick repository')}",
180 placeholder: "${_('Change repository') if c.repo_info.fork else _('Pick repository')}",
181 dropdownAutoWidth: true,
181 dropdownAutoWidth: true,
182 containerCssClass: "drop-menu",
182 containerCssClass: "drop-menu",
183 dropdownCssClass: "drop-menu-dropdown",
183 dropdownCssClass: "drop-menu-dropdown",
184 formatResult: formatResult,
184 formatResult: formatResult,
185 query: $.debounce(250, function(query){
185 query: $.debounce(250, function(query){
186 self = this;
186 self = this;
187 var cacheKey = query.term;
187 var cacheKey = query.term;
188 var cachedData = self.cachedDataSource[cacheKey];
188 var cachedData = self.cachedDataSource[cacheKey];
189
189
190 if (cachedData) {
190 if (cachedData) {
191 query.callback({results: cachedData.results});
191 query.callback({results: cachedData.results});
192 } else {
192 } else {
193 $.ajax({
193 $.ajax({
194 url: "${h.url('repo_list_data')}",
194 url: pyroutes.url('repo_list_data'),
195 data: {'query': query.term, repo_type: '${c.repo_info.repo_type}'},
195 data: {'query': query.term, repo_type: '${c.repo_info.repo_type}'},
196 dataType: 'json',
196 dataType: 'json',
197 type: 'GET',
197 type: 'GET',
198 success: function(data) {
198 success: function(data) {
199 data = repoTypeFilter(data);
199 data = repoTypeFilter(data);
200 self.cachedDataSource[cacheKey] = data;
200 self.cachedDataSource[cacheKey] = data;
201 query.callback({results: data.results});
201 query.callback({results: data.results});
202 },
202 },
203 error: function(data, textStatus, errorThrown) {
203 error: function(data, textStatus, errorThrown) {
204 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
204 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
205 }
205 }
206 })
206 })
207 }
207 }
208 })
208 })
209 });
209 });
210 </script>
210 </script>
211
211
@@ -1,157 +1,157 b''
1 <div class="panel panel-default">
1 <div class="panel panel-default">
2 <div class="panel-heading">
2 <div class="panel-heading">
3 <h3 class="panel-title">${_('Authentication Tokens')}</h3>
3 <h3 class="panel-title">${_('Authentication Tokens')}</h3>
4 </div>
4 </div>
5 <div class="panel-body">
5 <div class="panel-body">
6 <div class="apikeys_wrap">
6 <div class="apikeys_wrap">
7 <p>
7 <p>
8 ${_('Each token can have a role. Token with a role can be used only in given context, '
8 ${_('Each token can have a role. Token with a role can be used only in given context, '
9 'e.g. VCS tokens can be used together with the authtoken auth plugin for git/hg/svn operations only.')}
9 'e.g. VCS tokens can be used together with the authtoken auth plugin for git/hg/svn operations only.')}
10 </p>
10 </p>
11 <table class="rctable auth_tokens">
11 <table class="rctable auth_tokens">
12 <tr>
12 <tr>
13 <th>${_('Token')}</th>
13 <th>${_('Token')}</th>
14 <th>${_('Scope')}</th>
14 <th>${_('Scope')}</th>
15 <th>${_('Description')}</th>
15 <th>${_('Description')}</th>
16 <th>${_('Role')}</th>
16 <th>${_('Role')}</th>
17 <th>${_('Expiration')}</th>
17 <th>${_('Expiration')}</th>
18 <th>${_('Action')}</th>
18 <th>${_('Action')}</th>
19 </tr>
19 </tr>
20 %if c.user_auth_tokens:
20 %if c.user_auth_tokens:
21 %for auth_token in c.user_auth_tokens:
21 %for auth_token in c.user_auth_tokens:
22 <tr class="${'expired' if auth_token.expired else ''}">
22 <tr class="${'expired' if auth_token.expired else ''}">
23 <td class="truncate-wrap td-authtoken"><div class="user_auth_tokens truncate autoexpand"><code>${auth_token.api_key}</code></div></td>
23 <td class="truncate-wrap td-authtoken"><div class="user_auth_tokens truncate autoexpand"><code>${auth_token.api_key}</code></div></td>
24 <td class="td">${auth_token.scope_humanized}</td>
24 <td class="td">${auth_token.scope_humanized}</td>
25 <td class="td-wrap">${auth_token.description}</td>
25 <td class="td-wrap">${auth_token.description}</td>
26 <td class="td-tags">
26 <td class="td-tags">
27 <span class="tag disabled">${auth_token.role_humanized}</span>
27 <span class="tag disabled">${auth_token.role_humanized}</span>
28 </td>
28 </td>
29 <td class="td-exp">
29 <td class="td-exp">
30 %if auth_token.expires == -1:
30 %if auth_token.expires == -1:
31 ${_('never')}
31 ${_('never')}
32 %else:
32 %else:
33 %if auth_token.expired:
33 %if auth_token.expired:
34 <span style="text-decoration: line-through">${h.age_component(h.time_to_utcdatetime(auth_token.expires))}</span>
34 <span style="text-decoration: line-through">${h.age_component(h.time_to_utcdatetime(auth_token.expires))}</span>
35 %else:
35 %else:
36 ${h.age_component(h.time_to_utcdatetime(auth_token.expires))}
36 ${h.age_component(h.time_to_utcdatetime(auth_token.expires))}
37 %endif
37 %endif
38 %endif
38 %endif
39 </td>
39 </td>
40 <td class="td-action">
40 <td class="td-action">
41 ${h.secure_form(h.route_path('edit_user_auth_tokens_delete', user_id=c.user.user_id), method='post')}
41 ${h.secure_form(h.route_path('edit_user_auth_tokens_delete', user_id=c.user.user_id), method='post')}
42 ${h.hidden('del_auth_token',auth_token.api_key)}
42 ${h.hidden('del_auth_token',auth_token.api_key)}
43 <button class="btn btn-link btn-danger" type="submit"
43 <button class="btn btn-link btn-danger" type="submit"
44 onclick="return confirm('${_('Confirm to remove this auth token: %s') % auth_token.api_key}');">
44 onclick="return confirm('${_('Confirm to remove this auth token: %s') % auth_token.api_key}');">
45 ${_('Delete')}
45 ${_('Delete')}
46 </button>
46 </button>
47 ${h.end_form()}
47 ${h.end_form()}
48 </td>
48 </td>
49 </tr>
49 </tr>
50 %endfor
50 %endfor
51 %else:
51 %else:
52 <tr><td><div class="ip">${_('No additional auth tokens specified')}</div></td></tr>
52 <tr><td><div class="ip">${_('No additional auth tokens specified')}</div></td></tr>
53 %endif
53 %endif
54 </table>
54 </table>
55 </div>
55 </div>
56
56
57 <div class="user_auth_tokens">
57 <div class="user_auth_tokens">
58 ${h.secure_form(h.route_path('edit_user_auth_tokens_add', user_id=c.user.user_id), method='post')}
58 ${h.secure_form(h.route_path('edit_user_auth_tokens_add', user_id=c.user.user_id), method='post')}
59 <div class="form form-vertical">
59 <div class="form form-vertical">
60 <!-- fields -->
60 <!-- fields -->
61 <div class="fields">
61 <div class="fields">
62 <div class="field">
62 <div class="field">
63 <div class="label">
63 <div class="label">
64 <label for="new_email">${_('New authentication token')}:</label>
64 <label for="new_email">${_('New authentication token')}:</label>
65 </div>
65 </div>
66 <div class="input">
66 <div class="input">
67 ${h.text('description', class_='medium', placeholder=_('Description'))}
67 ${h.text('description', class_='medium', placeholder=_('Description'))}
68 ${h.select('lifetime', '', c.lifetime_options)}
68 ${h.select('lifetime', '', c.lifetime_options)}
69 ${h.select('role', '', c.role_options)}
69 ${h.select('role', '', c.role_options)}
70
70
71 % if c.allow_scoped_tokens:
71 % if c.allow_scoped_tokens:
72 ${h.hidden('scope_repo_id')}
72 ${h.hidden('scope_repo_id')}
73 % else:
73 % else:
74 ${h.select('scope_repo_id_disabled', '', ['Scopes available in EE edition'], disabled='disabled')}
74 ${h.select('scope_repo_id_disabled', '', ['Scopes available in EE edition'], disabled='disabled')}
75 % endif
75 % endif
76 </div>
76 </div>
77 <p class="help-block">
77 <p class="help-block">
78 ${_('Repository scope works only with tokens with VCS type.')}
78 ${_('Repository scope works only with tokens with VCS type.')}
79 </p>
79 </p>
80 </div>
80 </div>
81 <div class="buttons">
81 <div class="buttons">
82 ${h.submit('save',_('Add'),class_="btn")}
82 ${h.submit('save',_('Add'),class_="btn")}
83 ${h.reset('reset',_('Reset'),class_="btn")}
83 ${h.reset('reset',_('Reset'),class_="btn")}
84 </div>
84 </div>
85 </div>
85 </div>
86 </div>
86 </div>
87 ${h.end_form()}
87 ${h.end_form()}
88 </div>
88 </div>
89 </div>
89 </div>
90 </div>
90 </div>
91
91
92 <script>
92 <script>
93
93
94 $(document).ready(function(){
94 $(document).ready(function(){
95 var select2Options = {
95 var select2Options = {
96 'containerCssClass': "drop-menu",
96 'containerCssClass': "drop-menu",
97 'dropdownCssClass': "drop-menu-dropdown",
97 'dropdownCssClass': "drop-menu-dropdown",
98 'dropdownAutoWidth': true
98 'dropdownAutoWidth': true
99 };
99 };
100 $("#lifetime").select2(select2Options);
100 $("#lifetime").select2(select2Options);
101 $("#role").select2(select2Options);
101 $("#role").select2(select2Options);
102
102
103 var repoFilter = function(data) {
103 var repoFilter = function(data) {
104 var results = [];
104 var results = [];
105
105
106 if (!data.results[0]) {
106 if (!data.results[0]) {
107 return data
107 return data
108 }
108 }
109
109
110 $.each(data.results[0].children, function() {
110 $.each(data.results[0].children, function() {
111 // replace name to ID for submision
111 // replace name to ID for submision
112 this.id = this.obj.repo_id;
112 this.id = this.obj.repo_id;
113 results.push(this);
113 results.push(this);
114 });
114 });
115
115
116 data.results[0].children = results;
116 data.results[0].children = results;
117 return data;
117 return data;
118 };
118 };
119
119
120 $("#scope_repo_id_disabled").select2(select2Options);
120 $("#scope_repo_id_disabled").select2(select2Options);
121
121
122 $("#scope_repo_id").select2({
122 $("#scope_repo_id").select2({
123 cachedDataSource: {},
123 cachedDataSource: {},
124 minimumInputLength: 2,
124 minimumInputLength: 2,
125 placeholder: "${_('repository scope')}",
125 placeholder: "${_('repository scope')}",
126 dropdownAutoWidth: true,
126 dropdownAutoWidth: true,
127 containerCssClass: "drop-menu",
127 containerCssClass: "drop-menu",
128 dropdownCssClass: "drop-menu-dropdown",
128 dropdownCssClass: "drop-menu-dropdown",
129 formatResult: formatResult,
129 formatResult: formatResult,
130 query: $.debounce(250, function(query){
130 query: $.debounce(250, function(query){
131 self = this;
131 self = this;
132 var cacheKey = query.term;
132 var cacheKey = query.term;
133 var cachedData = self.cachedDataSource[cacheKey];
133 var cachedData = self.cachedDataSource[cacheKey];
134
134
135 if (cachedData) {
135 if (cachedData) {
136 query.callback({results: cachedData.results});
136 query.callback({results: cachedData.results});
137 } else {
137 } else {
138 $.ajax({
138 $.ajax({
139 url: "${h.url('repo_list_data')}",
139 url: pyroutes.url('repo_list_data'),
140 data: {'query': query.term},
140 data: {'query': query.term},
141 dataType: 'json',
141 dataType: 'json',
142 type: 'GET',
142 type: 'GET',
143 success: function(data) {
143 success: function(data) {
144 data = repoFilter(data);
144 data = repoFilter(data);
145 self.cachedDataSource[cacheKey] = data;
145 self.cachedDataSource[cacheKey] = data;
146 query.callback({results: data.results});
146 query.callback({results: data.results});
147 },
147 },
148 error: function(data, textStatus, errorThrown) {
148 error: function(data, textStatus, errorThrown) {
149 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
149 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
150 }
150 }
151 })
151 })
152 }
152 }
153 })
153 })
154 });
154 });
155
155
156 });
156 });
157 </script>
157 </script>
@@ -1,319 +1,257 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import json
21 import json
22
22
23 from mock import patch
23 from mock import patch
24 import pytest
24 import pytest
25 from pylons import tmpl_context as c
25 from pylons import tmpl_context as c
26
26
27 import rhodecode
27 import rhodecode
28 from rhodecode.lib.utils import map_groups
28 from rhodecode.lib.utils import map_groups
29 from rhodecode.model.db import Repository, User, RepoGroup
29 from rhodecode.model.db import Repository, User, RepoGroup
30 from rhodecode.model.meta import Session
30 from rhodecode.model.meta import Session
31 from rhodecode.model.repo import RepoModel
31 from rhodecode.model.repo import RepoModel
32 from rhodecode.model.repo_group import RepoGroupModel
32 from rhodecode.model.repo_group import RepoGroupModel
33 from rhodecode.model.settings import SettingsModel
33 from rhodecode.model.settings import SettingsModel
34 from rhodecode.tests import TestController, url, TEST_USER_ADMIN_LOGIN
34 from rhodecode.tests import TestController, url, TEST_USER_ADMIN_LOGIN
35 from rhodecode.tests.fixture import Fixture
35 from rhodecode.tests.fixture import Fixture
36
36
37
37
38 fixture = Fixture()
38 fixture = Fixture()
39
39
40
40
41 class TestHomeController(TestController):
41 class TestHomeController(TestController):
42
42
43 def test_index(self):
43 def test_index(self):
44 self.log_user()
44 self.log_user()
45 response = self.app.get(url(controller='home', action='index'))
45 response = self.app.get(url(controller='home', action='index'))
46 # if global permission is set
46 # if global permission is set
47 response.mustcontain('Add Repository')
47 response.mustcontain('Add Repository')
48
48
49 # search for objects inside the JavaScript JSON
49 # search for objects inside the JavaScript JSON
50 for repo in Repository.getAll():
50 for repo in Repository.getAll():
51 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
51 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
52
52
53 def test_index_contains_statics_with_ver(self):
53 def test_index_contains_statics_with_ver(self):
54 self.log_user()
54 self.log_user()
55 response = self.app.get(url(controller='home', action='index'))
55 response = self.app.get(url(controller='home', action='index'))
56
56
57 rhodecode_version_hash = c.rhodecode_version_hash
57 rhodecode_version_hash = c.rhodecode_version_hash
58 response.mustcontain('style.css?ver={0}'.format(rhodecode_version_hash))
58 response.mustcontain('style.css?ver={0}'.format(rhodecode_version_hash))
59 response.mustcontain('rhodecode-components.js?ver={0}'.format(rhodecode_version_hash))
59 response.mustcontain('rhodecode-components.js?ver={0}'.format(rhodecode_version_hash))
60
60
61 def test_index_contains_backend_specific_details(self, backend):
61 def test_index_contains_backend_specific_details(self, backend):
62 self.log_user()
62 self.log_user()
63 response = self.app.get(url(controller='home', action='index'))
63 response = self.app.get(url(controller='home', action='index'))
64 tip = backend.repo.get_commit().raw_id
64 tip = backend.repo.get_commit().raw_id
65
65
66 # html in javascript variable:
66 # html in javascript variable:
67 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
67 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
68 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
68 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
69
69
70 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
70 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
71 response.mustcontain("""Added a symlink""")
71 response.mustcontain("""Added a symlink""")
72
72
73 def test_index_with_anonymous_access_disabled(self):
73 def test_index_with_anonymous_access_disabled(self):
74 with fixture.anon_access(False):
74 with fixture.anon_access(False):
75 response = self.app.get(url(controller='home', action='index'),
75 response = self.app.get(url(controller='home', action='index'),
76 status=302)
76 status=302)
77 assert 'login' in response.location
77 assert 'login' in response.location
78
78
79 def test_index_page_on_groups(self, autologin_user, repo_group):
79 def test_index_page_on_groups(self, autologin_user, repo_group):
80 response = self.app.get(url('repo_group_home', group_name='gr1'))
80 response = self.app.get(url('repo_group_home', group_name='gr1'))
81 response.mustcontain("gr1/repo_in_group")
81 response.mustcontain("gr1/repo_in_group")
82
82
83 def test_index_page_on_group_with_trailing_slash(
83 def test_index_page_on_group_with_trailing_slash(
84 self, autologin_user, repo_group):
84 self, autologin_user, repo_group):
85 response = self.app.get(url('repo_group_home', group_name='gr1') + '/')
85 response = self.app.get(url('repo_group_home', group_name='gr1') + '/')
86 response.mustcontain("gr1/repo_in_group")
86 response.mustcontain("gr1/repo_in_group")
87
87
88 @pytest.fixture(scope='class')
88 @pytest.fixture(scope='class')
89 def repo_group(self, request):
89 def repo_group(self, request):
90 gr = fixture.create_repo_group('gr1')
90 gr = fixture.create_repo_group('gr1')
91 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
91 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
92
92
93 @request.addfinalizer
93 @request.addfinalizer
94 def cleanup():
94 def cleanup():
95 RepoModel().delete('gr1/repo_in_group')
95 RepoModel().delete('gr1/repo_in_group')
96 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
96 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
97 Session().commit()
97 Session().commit()
98
98
99 def test_index_with_name_with_tags(self, autologin_user):
99 def test_index_with_name_with_tags(self, autologin_user):
100 user = User.get_by_username('test_admin')
100 user = User.get_by_username('test_admin')
101 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
101 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
102 user.lastname = (
102 user.lastname = (
103 '<img src="/image2" onload="alert(\'Hello, World!\');">')
103 '<img src="/image2" onload="alert(\'Hello, World!\');">')
104 Session().add(user)
104 Session().add(user)
105 Session().commit()
105 Session().commit()
106
106
107 response = self.app.get(url(controller='home', action='index'))
107 response = self.app.get(url(controller='home', action='index'))
108 response.mustcontain(
108 response.mustcontain(
109 '&lt;img src=&#34;/image1&#34; onload=&#34;'
109 '&lt;img src=&#34;/image1&#34; onload=&#34;'
110 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
110 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
111 response.mustcontain(
111 response.mustcontain(
112 '&lt;img src=&#34;/image2&#34; onload=&#34;'
112 '&lt;img src=&#34;/image2&#34; onload=&#34;'
113 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
113 'alert(&#39;Hello, World!&#39;);&#34;&gt;')
114
114
115 @pytest.mark.parametrize("name, state", [
115 @pytest.mark.parametrize("name, state", [
116 ('Disabled', False),
116 ('Disabled', False),
117 ('Enabled', True),
117 ('Enabled', True),
118 ])
118 ])
119 def test_index_show_version(self, autologin_user, name, state):
119 def test_index_show_version(self, autologin_user, name, state):
120 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
120 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
121
121
122 sett = SettingsModel().create_or_update_setting(
122 sett = SettingsModel().create_or_update_setting(
123 'show_version', state, 'bool')
123 'show_version', state, 'bool')
124 Session().add(sett)
124 Session().add(sett)
125 Session().commit()
125 Session().commit()
126 SettingsModel().invalidate_settings_cache()
126 SettingsModel().invalidate_settings_cache()
127
127
128 response = self.app.get(url(controller='home', action='index'))
128 response = self.app.get(url(controller='home', action='index'))
129 if state is True:
129 if state is True:
130 response.mustcontain(version_string)
130 response.mustcontain(version_string)
131 if state is False:
131 if state is False:
132 response.mustcontain(no=[version_string])
132 response.mustcontain(no=[version_string])
133
133
134
134
135 def assert_and_get_content(result):
135 def assert_and_get_content(result):
136 repos = []
136 repos = []
137 groups = []
137 groups = []
138 commits = []
138 commits = []
139 for data in result:
139 for data in result:
140 for data_item in data['children']:
140 for data_item in data['children']:
141 assert data_item['id']
141 assert data_item['id']
142 assert data_item['text']
142 assert data_item['text']
143 assert data_item['url']
143 assert data_item['url']
144 if data_item['type'] == 'repo':
144 if data_item['type'] == 'repo':
145 repos.append(data_item)
145 repos.append(data_item)
146 elif data_item['type'] == 'group':
146 elif data_item['type'] == 'group':
147 groups.append(data_item)
147 groups.append(data_item)
148 elif data_item['type'] == 'commit':
148 elif data_item['type'] == 'commit':
149 commits.append(data_item)
149 commits.append(data_item)
150 else:
150 else:
151 raise Exception('invalid type %s' % data_item['type'])
151 raise Exception('invalid type %s' % data_item['type'])
152
152
153 return repos, groups, commits
153 return repos, groups, commits
154
154
155
155
156 class TestGotoSwitcherData(TestController):
156 class TestGotoSwitcherData(TestController):
157 required_repos_with_groups = [
157 required_repos_with_groups = [
158 'abc',
158 'abc',
159 'abc-fork',
159 'abc-fork',
160 'forks/abcd',
160 'forks/abcd',
161 'abcd',
161 'abcd',
162 'abcde',
162 'abcde',
163 'a/abc',
163 'a/abc',
164 'aa/abc',
164 'aa/abc',
165 'aaa/abc',
165 'aaa/abc',
166 'aaaa/abc',
166 'aaaa/abc',
167 'repos_abc/aaa/abc',
167 'repos_abc/aaa/abc',
168 'abc_repos/abc',
168 'abc_repos/abc',
169 'abc_repos/abcd',
169 'abc_repos/abcd',
170 'xxx/xyz',
170 'xxx/xyz',
171 'forked-abc/a/abc'
171 'forked-abc/a/abc'
172 ]
172 ]
173
173
174 @pytest.fixture(autouse=True, scope='class')
174 @pytest.fixture(autouse=True, scope='class')
175 def prepare(self, request, pylonsapp):
175 def prepare(self, request, pylonsapp):
176 for repo_and_group in self.required_repos_with_groups:
176 for repo_and_group in self.required_repos_with_groups:
177 # create structure of groups and return the last group
177 # create structure of groups and return the last group
178
178
179 repo_group = map_groups(repo_and_group)
179 repo_group = map_groups(repo_and_group)
180
180
181 RepoModel()._create_repo(
181 RepoModel()._create_repo(
182 repo_and_group, 'hg', 'test-ac', TEST_USER_ADMIN_LOGIN,
182 repo_and_group, 'hg', 'test-ac', TEST_USER_ADMIN_LOGIN,
183 repo_group=getattr(repo_group, 'group_id', None))
183 repo_group=getattr(repo_group, 'group_id', None))
184
184
185 Session().commit()
185 Session().commit()
186
186
187 request.addfinalizer(self.cleanup)
187 request.addfinalizer(self.cleanup)
188
188
189 def cleanup(self):
189 def cleanup(self):
190 # first delete all repos
190 # first delete all repos
191 for repo_and_groups in self.required_repos_with_groups:
191 for repo_and_groups in self.required_repos_with_groups:
192 repo = Repository.get_by_repo_name(repo_and_groups)
192 repo = Repository.get_by_repo_name(repo_and_groups)
193 if repo:
193 if repo:
194 RepoModel().delete(repo)
194 RepoModel().delete(repo)
195 Session().commit()
195 Session().commit()
196
196
197 # then delete all empty groups
197 # then delete all empty groups
198 for repo_and_groups in self.required_repos_with_groups:
198 for repo_and_groups in self.required_repos_with_groups:
199 if '/' in repo_and_groups:
199 if '/' in repo_and_groups:
200 r_group = repo_and_groups.rsplit('/', 1)[0]
200 r_group = repo_and_groups.rsplit('/', 1)[0]
201 repo_group = RepoGroup.get_by_group_name(r_group)
201 repo_group = RepoGroup.get_by_group_name(r_group)
202 if not repo_group:
202 if not repo_group:
203 continue
203 continue
204 parents = repo_group.parents
204 parents = repo_group.parents
205 RepoGroupModel().delete(repo_group, force_delete=True)
205 RepoGroupModel().delete(repo_group, force_delete=True)
206 Session().commit()
206 Session().commit()
207
207
208 for el in reversed(parents):
208 for el in reversed(parents):
209 RepoGroupModel().delete(el, force_delete=True)
209 RepoGroupModel().delete(el, force_delete=True)
210 Session().commit()
210 Session().commit()
211
211
212 def test_returns_list_of_repos_and_groups(self):
212 def test_returns_list_of_repos_and_groups(self):
213 self.log_user()
213 self.log_user()
214
214
215 response = self.app.get(
215 response = self.app.get(
216 url(controller='home', action='goto_switcher_data'),
216 url(controller='home', action='goto_switcher_data'),
217 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
217 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
218 result = json.loads(response.body)['results']
218 result = json.loads(response.body)['results']
219
219
220 repos, groups, commits = assert_and_get_content(result)
220 repos, groups, commits = assert_and_get_content(result)
221
221
222 assert len(repos) == len(Repository.get_all())
222 assert len(repos) == len(Repository.get_all())
223 assert len(groups) == len(RepoGroup.get_all())
223 assert len(groups) == len(RepoGroup.get_all())
224 assert len(commits) == 0
224 assert len(commits) == 0
225
225
226 def test_returns_list_of_repos_and_groups_filtered(self):
226 def test_returns_list_of_repos_and_groups_filtered(self):
227 self.log_user()
227 self.log_user()
228
228
229 response = self.app.get(
229 response = self.app.get(
230 url(controller='home', action='goto_switcher_data'),
230 url(controller='home', action='goto_switcher_data'),
231 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
231 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
232 params={'query': 'abc'}, status=200)
232 params={'query': 'abc'}, status=200)
233 result = json.loads(response.body)['results']
233 result = json.loads(response.body)['results']
234
234
235 repos, groups, commits = assert_and_get_content(result)
235 repos, groups, commits = assert_and_get_content(result)
236
236
237 assert len(repos) == 13
237 assert len(repos) == 13
238 assert len(groups) == 5
238 assert len(groups) == 5
239 assert len(commits) == 0
239 assert len(commits) == 0
240
240
241 def test_returns_list_of_properly_sorted_and_filtered(self):
241 def test_returns_list_of_properly_sorted_and_filtered(self):
242 self.log_user()
242 self.log_user()
243
243
244 response = self.app.get(
244 response = self.app.get(
245 url(controller='home', action='goto_switcher_data'),
245 url(controller='home', action='goto_switcher_data'),
246 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
246 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
247 params={'query': 'abc'}, status=200)
247 params={'query': 'abc'}, status=200)
248 result = json.loads(response.body)['results']
248 result = json.loads(response.body)['results']
249
249
250 repos, groups, commits = assert_and_get_content(result)
250 repos, groups, commits = assert_and_get_content(result)
251
251
252 test_repos = [x['text'] for x in repos[:4]]
252 test_repos = [x['text'] for x in repos[:4]]
253 assert ['abc', 'abcd', 'a/abc', 'abcde'] == test_repos
253 assert ['abc', 'abcd', 'a/abc', 'abcde'] == test_repos
254
254
255 test_groups = [x['text'] for x in groups[:4]]
255 test_groups = [x['text'] for x in groups[:4]]
256 assert ['abc_repos', 'repos_abc',
256 assert ['abc_repos', 'repos_abc',
257 'forked-abc', 'forked-abc/a'] == test_groups
257 'forked-abc', 'forked-abc/a'] == test_groups
258
259
260 class TestRepoListData(TestController):
261 def test_returns_list_of_repos_and_groups(self, user_util):
262 self.log_user()
263
264 response = self.app.get(
265 url(controller='home', action='repo_list_data'),
266 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', }, status=200)
267 result = json.loads(response.body)['results']
268
269 repos, groups, commits = assert_and_get_content(result)
270
271 assert len(repos) == len(Repository.get_all())
272 assert len(groups) == 0
273 assert len(commits) == 0
274
275 def test_returns_list_of_repos_and_groups_filtered(self):
276 self.log_user()
277
278 response = self.app.get(
279 url(controller='home', action='repo_list_data'),
280 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
281 params={'query': 'vcs_test_git'}, status=200)
282 result = json.loads(response.body)['results']
283
284 repos, groups, commits = assert_and_get_content(result)
285
286 assert len(repos) == len(Repository.query().filter(
287 Repository.repo_name.ilike('%vcs_test_git%')).all())
288 assert len(groups) == 0
289 assert len(commits) == 0
290
291 def test_returns_list_of_repos_and_groups_filtered_with_type(self):
292 self.log_user()
293
294 response = self.app.get(
295 url(controller='home', action='repo_list_data'),
296 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
297 params={'query': 'vcs_test_git', 'repo_type': 'git'}, status=200)
298 result = json.loads(response.body)['results']
299
300 repos, groups, commits = assert_and_get_content(result)
301
302 assert len(repos) == len(Repository.query().filter(
303 Repository.repo_name.ilike('%vcs_test_git%')).all())
304 assert len(groups) == 0
305 assert len(commits) == 0
306
307 def test_returns_list_of_repos_non_ascii_query(self):
308 self.log_user()
309 response = self.app.get(
310 url(controller='home', action='repo_list_data'),
311 headers={'X-REQUESTED-WITH': 'XMLHttpRequest', },
312 params={'query': 'ć_vcs_test_ą', 'repo_type': 'git'}, status=200)
313 result = json.loads(response.body)['results']
314
315 repos, groups, commits = assert_and_get_content(result)
316
317 assert len(repos) == 0
318 assert len(groups) == 0
319 assert len(commits) == 0
General Comments 0
You need to be logged in to leave comments. Login now