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