##// END OF EJS Templates
my-account: migrated left over controller functions into pyramid views....
dan -
r1892:89ddfad2 default
parent child Browse files
Show More
@@ -0,0 +1,205 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 # -*- coding: utf-8 -*-
21
22 # Copyright (C) 2016-2017 RhodeCode GmbH
23 #
24 # This program is free software: you can redistribute it and/or modify
25 # it under the terms of the GNU Affero General Public License, version 3
26 # (only), as published by the Free Software Foundation.
27 #
28 # This program is distributed in the hope that it will be useful,
29 # but WITHOUT ANY WARRANTY; without even the implied warranty of
30 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 # GNU General Public License for more details.
32 #
33 # You should have received a copy of the GNU Affero General Public License
34 # along with this program. If not, see <http://www.gnu.org/licenses/>.
35 #
36 # This program is dual-licensed. If you wish to learn more about the
37 # RhodeCode Enterprise Edition, including its added features, Support services,
38 # and proprietary license terms, please see https://rhodecode.com/licenses/
39
40 import pytest
41
42 from rhodecode.model.db import User
43 from rhodecode.tests import TestController, assert_session_flash
44 from rhodecode.lib import helpers as h
45
46
47 def route_path(name, params=None, **kwargs):
48 import urllib
49 from rhodecode.apps._base import ADMIN_PREFIX
50
51 base_url = {
52 'my_account_edit': ADMIN_PREFIX + '/my_account/edit',
53 'my_account_update': ADMIN_PREFIX + '/my_account/update',
54 'my_account_pullrequests': ADMIN_PREFIX + '/my_account/pull_requests',
55 'my_account_pullrequests_data': ADMIN_PREFIX + '/my_account/pull_requests/data',
56 }[name].format(**kwargs)
57
58 if params:
59 base_url = '{}?{}'.format(base_url, urllib.urlencode(params))
60 return base_url
61
62
63 class TestMyAccountEdit(TestController):
64
65 def test_my_account_edit(self):
66 self.log_user()
67 response = self.app.get(route_path('my_account_edit'))
68
69 response.mustcontain('value="test_admin')
70
71 @pytest.mark.backends("git", "hg")
72 def test_my_account_my_pullrequests(self, pr_util):
73 self.log_user()
74 response = self.app.get(route_path('my_account_pullrequests'))
75 response.mustcontain('There are currently no open pull '
76 'requests requiring your participation.')
77
78 @pytest.mark.backends("git", "hg")
79 def test_my_account_my_pullrequests_data(self, pr_util, xhr_header):
80 self.log_user()
81 response = self.app.get(route_path('my_account_pullrequests_data'),
82 extra_environ=xhr_header)
83 assert response.json == {
84 u'data': [], u'draw': None,
85 u'recordsFiltered': 0, u'recordsTotal': 0}
86
87 pr = pr_util.create_pull_request(title='TestMyAccountPR')
88 expected = {
89 'author_raw': 'RhodeCode Admin',
90 'name_raw': pr.pull_request_id
91 }
92 response = self.app.get(route_path('my_account_pullrequests_data'),
93 extra_environ=xhr_header)
94 assert response.json['recordsTotal'] == 1
95 assert response.json['data'][0]['author_raw'] == expected['author_raw']
96
97 assert response.json['data'][0]['author_raw'] == expected['author_raw']
98 assert response.json['data'][0]['name_raw'] == expected['name_raw']
99
100 @pytest.mark.parametrize(
101 "name, attrs", [
102 ('firstname', {'firstname': 'new_username'}),
103 ('lastname', {'lastname': 'new_username'}),
104 ('admin', {'admin': True}),
105 ('admin', {'admin': False}),
106 ('extern_type', {'extern_type': 'ldap'}),
107 ('extern_type', {'extern_type': None}),
108 # ('extern_name', {'extern_name': 'test'}),
109 # ('extern_name', {'extern_name': None}),
110 ('active', {'active': False}),
111 ('active', {'active': True}),
112 ('email', {'email': 'some@email.com'}),
113 ])
114 def test_my_account_update(self, name, attrs, user_util):
115 usr = user_util.create_user(password='qweqwe')
116 params = usr.get_api_data() # current user data
117 user_id = usr.user_id
118 self.log_user(
119 username=usr.username, password='qweqwe')
120
121 params.update({'password_confirmation': ''})
122 params.update({'new_password': ''})
123 params.update({'extern_type': 'rhodecode'})
124 params.update({'extern_name': 'rhodecode'})
125 params.update({'csrf_token': self.csrf_token})
126
127 params.update(attrs)
128 # my account page cannot set language param yet, only for admins
129 del params['language']
130 response = self.app.post(route_path('my_account_update'), params)
131
132 assert_session_flash(
133 response, 'Your account was updated successfully')
134
135 del params['csrf_token']
136
137 updated_user = User.get(user_id)
138 updated_params = updated_user.get_api_data()
139 updated_params.update({'password_confirmation': ''})
140 updated_params.update({'new_password': ''})
141
142 params['last_login'] = updated_params['last_login']
143 params['last_activity'] = updated_params['last_activity']
144 # my account page cannot set language param yet, only for admins
145 # but we get this info from API anyway
146 params['language'] = updated_params['language']
147
148 if name == 'email':
149 params['emails'] = [attrs['email']]
150 if name == 'extern_type':
151 # cannot update this via form, expected value is original one
152 params['extern_type'] = "rhodecode"
153 if name == 'extern_name':
154 # cannot update this via form, expected value is original one
155 params['extern_name'] = str(user_id)
156 if name == 'active':
157 # my account cannot deactivate account
158 params['active'] = True
159 if name == 'admin':
160 # my account cannot make you an admin !
161 params['admin'] = False
162
163 assert params == updated_params
164
165 def test_my_account_update_err_email_exists(self):
166 self.log_user()
167
168 new_email = 'test_regular@mail.com' # already existing email
169 params = {
170 'username': 'test_admin',
171 'new_password': 'test12',
172 'password_confirmation': 'test122',
173 'firstname': 'NewName',
174 'lastname': 'NewLastname',
175 'email': new_email,
176 'csrf_token': self.csrf_token,
177 }
178
179 response = self.app.post(route_path('my_account_update'),
180 params=params)
181
182 response.mustcontain('This e-mail address is already taken')
183
184 def test_my_account_update_bad_email_address(self):
185 self.log_user('test_regular2', 'test12')
186
187 new_email = 'newmail.pl'
188 params = {
189 'username': 'test_admin',
190 'new_password': 'test12',
191 'password_confirmation': 'test122',
192 'firstname': 'NewName',
193 'lastname': 'NewLastname',
194 'email': new_email,
195 'csrf_token': self.csrf_token,
196 }
197 response = self.app.post(route_path('my_account_update'),
198 params=params)
199
200 response.mustcontain('An email address must contain a single @')
201 from rhodecode.model import validators
202 msg = validators.ValidUsername(
203 edit=False, old_data={})._messages['username_exists']
204 msg = h.html_escape(msg % {'username': 'test_admin'})
205 response.mustcontain(u"%s" % msg)
@@ -1,134 +1,140 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 import pytest
22 import pytest
23
23
24 import rhodecode
24 import rhodecode
25 from rhodecode.model.db import Repository
25 from rhodecode.model.db import Repository
26 from rhodecode.model.meta import Session
26 from rhodecode.model.meta import Session
27 from rhodecode.model.repo import RepoModel
27 from rhodecode.model.repo import RepoModel
28 from rhodecode.model.repo_group import RepoGroupModel
28 from rhodecode.model.repo_group import RepoGroupModel
29 from rhodecode.model.settings import SettingsModel
29 from rhodecode.model.settings import SettingsModel
30 from rhodecode.tests import TestController
30 from rhodecode.tests import TestController
31 from rhodecode.tests.fixture import Fixture
31 from rhodecode.tests.fixture import Fixture
32 from rhodecode.lib import helpers as h
32 from rhodecode.lib import helpers as h
33
33
34 fixture = Fixture()
34 fixture = Fixture()
35
35
36
36
37 def route_path(name, **kwargs):
37 def route_path(name, **kwargs):
38 return {
38 return {
39 'home': '/',
39 'home': '/',
40 'repo_group_home': '/{repo_group_name}'
40 'repo_group_home': '/{repo_group_name}'
41 }[name].format(**kwargs)
41 }[name].format(**kwargs)
42
42
43
43
44 class TestHomeController(TestController):
44 class TestHomeController(TestController):
45
45
46 def test_index(self):
46 def test_index(self):
47 self.log_user()
47 self.log_user()
48 response = self.app.get(route_path('home'))
48 response = self.app.get(route_path('home'))
49 # if global permission is set
49 # if global permission is set
50 response.mustcontain('Add Repository')
50 response.mustcontain('Add Repository')
51
51
52 # search for objects inside the JavaScript JSON
52 # search for objects inside the JavaScript JSON
53 for repo in Repository.getAll():
53 for repo in Repository.getAll():
54 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
54 response.mustcontain('"name_raw": "%s"' % repo.repo_name)
55
55
56 def test_index_contains_statics_with_ver(self):
56 def test_index_contains_statics_with_ver(self):
57 from pylons import tmpl_context as c
57 from pylons import tmpl_context as c
58
58
59 self.log_user()
59 self.log_user()
60 response = self.app.get(route_path('home'))
60 response = self.app.get(route_path('home'))
61
61
62 rhodecode_version_hash = c.rhodecode_version_hash
62 rhodecode_version_hash = c.rhodecode_version_hash
63 response.mustcontain('style.css?ver={0}'.format(rhodecode_version_hash))
63 response.mustcontain('style.css?ver={0}'.format(rhodecode_version_hash))
64 response.mustcontain('rhodecode-components.js?ver={0}'.format(rhodecode_version_hash))
64 response.mustcontain('rhodecode-components.js?ver={0}'.format(rhodecode_version_hash))
65
65
66 def test_index_contains_backend_specific_details(self, backend):
66 def test_index_contains_backend_specific_details(self, backend):
67 self.log_user()
67 self.log_user()
68 response = self.app.get(route_path('home'))
68 response = self.app.get(route_path('home'))
69 tip = backend.repo.get_commit().raw_id
69 tip = backend.repo.get_commit().raw_id
70
70
71 # html in javascript variable:
71 # html in javascript variable:
72 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
72 response.mustcontain(r'<i class=\"icon-%s\"' % (backend.alias, ))
73 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
73 response.mustcontain(r'href=\"/%s\"' % (backend.repo_name, ))
74
74
75 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
75 response.mustcontain("""/%s/changeset/%s""" % (backend.repo_name, tip))
76 response.mustcontain("""Added a symlink""")
76 response.mustcontain("""Added a symlink""")
77
77
78 def test_index_with_anonymous_access_disabled(self):
78 def test_index_with_anonymous_access_disabled(self):
79 with fixture.anon_access(False):
79 with fixture.anon_access(False):
80 response = self.app.get(route_path('home'), status=302)
80 response = self.app.get(route_path('home'), status=302)
81 assert 'login' in response.location
81 assert 'login' in response.location
82
82
83 def test_index_page_on_groups(self, autologin_user, repo_group):
83 def test_index_page_on_groups(self, autologin_user, repo_group):
84 response = self.app.get(route_path('repo_group_home', repo_group_name='gr1'))
84 response = self.app.get(route_path('repo_group_home', repo_group_name='gr1'))
85 response.mustcontain("gr1/repo_in_group")
85 response.mustcontain("gr1/repo_in_group")
86
86
87 def test_index_page_on_group_with_trailing_slash(
87 def test_index_page_on_group_with_trailing_slash(
88 self, autologin_user, repo_group):
88 self, autologin_user, repo_group):
89 response = self.app.get(route_path('repo_group_home', repo_group_name='gr1') + '/')
89 response = self.app.get(route_path('repo_group_home', repo_group_name='gr1') + '/')
90 response.mustcontain("gr1/repo_in_group")
90 response.mustcontain("gr1/repo_in_group")
91
91
92 @pytest.fixture(scope='class')
92 @pytest.fixture(scope='class')
93 def repo_group(self, request):
93 def repo_group(self, request):
94 gr = fixture.create_repo_group('gr1')
94 gr = fixture.create_repo_group('gr1')
95 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
95 fixture.create_repo(name='gr1/repo_in_group', repo_group=gr)
96
96
97 @request.addfinalizer
97 @request.addfinalizer
98 def cleanup():
98 def cleanup():
99 RepoModel().delete('gr1/repo_in_group')
99 RepoModel().delete('gr1/repo_in_group')
100 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
100 RepoGroupModel().delete(repo_group='gr1', force_delete=True)
101 Session().commit()
101 Session().commit()
102
102
103 def test_index_with_name_with_tags(self, user_util, autologin_user):
103 def test_index_with_name_with_tags(self, user_util, autologin_user):
104 user = user_util.create_user()
104 user = user_util.create_user()
105 username = user.username
105 username = user.username
106 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
106 user.name = '<img src="/image1" onload="alert(\'Hello, World!\');">'
107 user.lastname = '#"><img src=x onerror=prompt(document.cookie);>'
107 user.lastname = '#"><img src=x onerror=prompt(document.cookie);>'
108
108
109 Session().add(user)
109 Session().add(user)
110 Session().commit()
110 Session().commit()
111 user_util.create_repo(owner=username)
111 user_util.create_repo(owner=username)
112
112
113 response = self.app.get(route_path('home'))
113 response = self.app.get(route_path('home'))
114 response.mustcontain(h.html_escape(user.first_name))
114 response.mustcontain(h.html_escape(user.first_name))
115 response.mustcontain(h.html_escape(user.last_name))
115 response.mustcontain(h.html_escape(user.last_name))
116
116
117 @pytest.mark.parametrize("name, state", [
117 @pytest.mark.parametrize("name, state", [
118 ('Disabled', False),
118 ('Disabled', False),
119 ('Enabled', True),
119 ('Enabled', True),
120 ])
120 ])
121 def test_index_show_version(self, autologin_user, name, state):
121 def test_index_show_version(self, autologin_user, name, state):
122 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
122 version_string = 'RhodeCode Enterprise %s' % rhodecode.__version__
123
123
124 sett = SettingsModel().create_or_update_setting(
124 sett = SettingsModel().create_or_update_setting(
125 'show_version', state, 'bool')
125 'show_version', state, 'bool')
126 Session().add(sett)
126 Session().add(sett)
127 Session().commit()
127 Session().commit()
128 SettingsModel().invalidate_settings_cache()
128 SettingsModel().invalidate_settings_cache()
129
129
130 response = self.app.get(route_path('home'))
130 response = self.app.get(route_path('home'))
131 if state is True:
131 if state is True:
132 response.mustcontain(version_string)
132 response.mustcontain(version_string)
133 if state is False:
133 if state is False:
134 response.mustcontain(no=[version_string])
134 response.mustcontain(no=[version_string])
135
136 def test_logout_form_contains_csrf(self, autologin_user, csrf_token):
137 response = self.app.get(route_path('home'))
138 assert_response = response.assert_response()
139 element = assert_response.get_element('.logout #csrf_token')
140 assert element.value == csrf_token
@@ -1,85 +1,104 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 from rhodecode.apps._base import ADMIN_PREFIX
22 from rhodecode.apps._base import ADMIN_PREFIX
23
23
24
24
25 def includeme(config):
25 def includeme(config):
26
26
27 config.add_route(
27 config.add_route(
28 name='my_account_profile',
28 name='my_account_profile',
29 pattern=ADMIN_PREFIX + '/my_account/profile')
29 pattern=ADMIN_PREFIX + '/my_account/profile')
30
30
31 # my account edit details
32 config.add_route(
33 name='my_account_edit',
34 pattern=ADMIN_PREFIX + '/my_account/edit')
35 config.add_route(
36 name='my_account_update',
37 pattern=ADMIN_PREFIX + '/my_account/update')
38
39 # my account password
31 config.add_route(
40 config.add_route(
32 name='my_account_password',
41 name='my_account_password',
33 pattern=ADMIN_PREFIX + '/my_account/password')
42 pattern=ADMIN_PREFIX + '/my_account/password')
34
43
35 config.add_route(
44 config.add_route(
36 name='my_account_password_update',
45 name='my_account_password_update',
37 pattern=ADMIN_PREFIX + '/my_account/password')
46 pattern=ADMIN_PREFIX + '/my_account/password')
38
47
48 # my account tokens
39 config.add_route(
49 config.add_route(
40 name='my_account_auth_tokens',
50 name='my_account_auth_tokens',
41 pattern=ADMIN_PREFIX + '/my_account/auth_tokens')
51 pattern=ADMIN_PREFIX + '/my_account/auth_tokens')
42 config.add_route(
52 config.add_route(
43 name='my_account_auth_tokens_add',
53 name='my_account_auth_tokens_add',
44 pattern=ADMIN_PREFIX + '/my_account/auth_tokens/new')
54 pattern=ADMIN_PREFIX + '/my_account/auth_tokens/new')
45 config.add_route(
55 config.add_route(
46 name='my_account_auth_tokens_delete',
56 name='my_account_auth_tokens_delete',
47 pattern=ADMIN_PREFIX + '/my_account/auth_tokens/delete')
57 pattern=ADMIN_PREFIX + '/my_account/auth_tokens/delete')
48
58
59 # my account emails
49 config.add_route(
60 config.add_route(
50 name='my_account_emails',
61 name='my_account_emails',
51 pattern=ADMIN_PREFIX + '/my_account/emails')
62 pattern=ADMIN_PREFIX + '/my_account/emails')
52 config.add_route(
63 config.add_route(
53 name='my_account_emails_add',
64 name='my_account_emails_add',
54 pattern=ADMIN_PREFIX + '/my_account/emails/new')
65 pattern=ADMIN_PREFIX + '/my_account/emails/new')
55 config.add_route(
66 config.add_route(
56 name='my_account_emails_delete',
67 name='my_account_emails_delete',
57 pattern=ADMIN_PREFIX + '/my_account/emails/delete')
68 pattern=ADMIN_PREFIX + '/my_account/emails/delete')
58
69
59 config.add_route(
70 config.add_route(
60 name='my_account_repos',
71 name='my_account_repos',
61 pattern=ADMIN_PREFIX + '/my_account/repos')
72 pattern=ADMIN_PREFIX + '/my_account/repos')
62
73
63 config.add_route(
74 config.add_route(
64 name='my_account_watched',
75 name='my_account_watched',
65 pattern=ADMIN_PREFIX + '/my_account/watched')
76 pattern=ADMIN_PREFIX + '/my_account/watched')
66
77
67 config.add_route(
78 config.add_route(
68 name='my_account_perms',
79 name='my_account_perms',
69 pattern=ADMIN_PREFIX + '/my_account/perms')
80 pattern=ADMIN_PREFIX + '/my_account/perms')
70
81
71 config.add_route(
82 config.add_route(
72 name='my_account_notifications',
83 name='my_account_notifications',
73 pattern=ADMIN_PREFIX + '/my_account/notifications')
84 pattern=ADMIN_PREFIX + '/my_account/notifications')
74
85
75 config.add_route(
86 config.add_route(
76 name='my_account_notifications_toggle_visibility',
87 name='my_account_notifications_toggle_visibility',
77 pattern=ADMIN_PREFIX + '/my_account/toggle_visibility')
88 pattern=ADMIN_PREFIX + '/my_account/toggle_visibility')
78
89
90 # my account pull requests
91 config.add_route(
92 name='my_account_pullrequests',
93 pattern=ADMIN_PREFIX + '/my_account/pull_requests')
94 config.add_route(
95 name='my_account_pullrequests_data',
96 pattern=ADMIN_PREFIX + '/my_account/pull_requests/data')
97
79 # channelstream test
98 # channelstream test
80 config.add_route(
99 config.add_route(
81 name='my_account_notifications_test_channelstream',
100 name='my_account_notifications_test_channelstream',
82 pattern=ADMIN_PREFIX + '/my_account/test_channelstream')
101 pattern=ADMIN_PREFIX + '/my_account/test_channelstream')
83
102
84 # Scan module for configuration decorators.
103 # Scan module for configuration decorators.
85 config.scan()
104 config.scan()
@@ -1,399 +1,584 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2017 RhodeCode GmbH
3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import datetime
22 import datetime
23
23
24 import formencode
24 import formencode
25 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
26 from pyramid.view import view_config
26 from pyramid.view import view_config
27 from pyramid.renderers import render
28 from pyramid.response import Response
27
29
28 from rhodecode.apps._base import BaseAppView
30 from rhodecode.apps._base import BaseAppView, DataGridAppView
29 from rhodecode import forms
31 from rhodecode import forms
30 from rhodecode.lib import helpers as h
32 from rhodecode.lib import helpers as h
31 from rhodecode.lib import audit_logger
33 from rhodecode.lib import audit_logger
32 from rhodecode.lib.ext_json import json
34 from rhodecode.lib.ext_json import json
33 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired
35 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired
34 from rhodecode.lib.channelstream import channelstream_request, \
36 from rhodecode.lib.channelstream import channelstream_request, \
35 ChannelstreamException
37 ChannelstreamException
36 from rhodecode.lib.utils2 import safe_int, md5
38 from rhodecode.lib.utils import PartialRenderer
39 from rhodecode.lib.utils2 import safe_int, md5, str2bool
37 from rhodecode.model.auth_token import AuthTokenModel
40 from rhodecode.model.auth_token import AuthTokenModel
41 from rhodecode.model.comment import CommentsModel
38 from rhodecode.model.db import (
42 from rhodecode.model.db import (
39 Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload)
43 Repository, UserEmailMap, UserApiKeys, UserFollowing, joinedload,
44 PullRequest)
45 from rhodecode.model.forms import UserForm
40 from rhodecode.model.meta import Session
46 from rhodecode.model.meta import Session
47 from rhodecode.model.pull_request import PullRequestModel
41 from rhodecode.model.scm import RepoList
48 from rhodecode.model.scm import RepoList
42 from rhodecode.model.user import UserModel
49 from rhodecode.model.user import UserModel
43 from rhodecode.model.repo import RepoModel
50 from rhodecode.model.repo import RepoModel
44 from rhodecode.model.validation_schema.schemas import user_schema
51 from rhodecode.model.validation_schema.schemas import user_schema
45
52
46 log = logging.getLogger(__name__)
53 log = logging.getLogger(__name__)
47
54
48
55
49 class MyAccountView(BaseAppView):
56 class MyAccountView(BaseAppView, DataGridAppView):
50 ALLOW_SCOPED_TOKENS = False
57 ALLOW_SCOPED_TOKENS = False
51 """
58 """
52 This view has alternative version inside EE, if modified please take a look
59 This view has alternative version inside EE, if modified please take a look
53 in there as well.
60 in there as well.
54 """
61 """
55
62
56 def load_default_context(self):
63 def load_default_context(self):
57 c = self._get_local_tmpl_context()
64 c = self._get_local_tmpl_context()
58 c.user = c.auth_user.get_instance()
65 c.user = c.auth_user.get_instance()
59 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
66 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
60 self._register_global_c(c)
67 self._register_global_c(c)
61 return c
68 return c
62
69
63 @LoginRequired()
70 @LoginRequired()
64 @NotAnonymous()
71 @NotAnonymous()
65 @view_config(
72 @view_config(
66 route_name='my_account_profile', request_method='GET',
73 route_name='my_account_profile', request_method='GET',
67 renderer='rhodecode:templates/admin/my_account/my_account.mako')
74 renderer='rhodecode:templates/admin/my_account/my_account.mako')
68 def my_account_profile(self):
75 def my_account_profile(self):
69 c = self.load_default_context()
76 c = self.load_default_context()
70 c.active = 'profile'
77 c.active = 'profile'
71 return self._get_template_context(c)
78 return self._get_template_context(c)
72
79
73 @LoginRequired()
80 @LoginRequired()
74 @NotAnonymous()
81 @NotAnonymous()
75 @view_config(
82 @view_config(
76 route_name='my_account_password', request_method='GET',
83 route_name='my_account_password', request_method='GET',
77 renderer='rhodecode:templates/admin/my_account/my_account.mako')
84 renderer='rhodecode:templates/admin/my_account/my_account.mako')
78 def my_account_password(self):
85 def my_account_password(self):
79 c = self.load_default_context()
86 c = self.load_default_context()
80 c.active = 'password'
87 c.active = 'password'
81 c.extern_type = c.user.extern_type
88 c.extern_type = c.user.extern_type
82
89
83 schema = user_schema.ChangePasswordSchema().bind(
90 schema = user_schema.ChangePasswordSchema().bind(
84 username=c.user.username)
91 username=c.user.username)
85
92
86 form = forms.Form(
93 form = forms.Form(
87 schema, buttons=(forms.buttons.save, forms.buttons.reset))
94 schema, buttons=(forms.buttons.save, forms.buttons.reset))
88
95
89 c.form = form
96 c.form = form
90 return self._get_template_context(c)
97 return self._get_template_context(c)
91
98
92 @LoginRequired()
99 @LoginRequired()
93 @NotAnonymous()
100 @NotAnonymous()
94 @CSRFRequired()
101 @CSRFRequired()
95 @view_config(
102 @view_config(
96 route_name='my_account_password', request_method='POST',
103 route_name='my_account_password', request_method='POST',
97 renderer='rhodecode:templates/admin/my_account/my_account.mako')
104 renderer='rhodecode:templates/admin/my_account/my_account.mako')
98 def my_account_password_update(self):
105 def my_account_password_update(self):
99 _ = self.request.translate
106 _ = self.request.translate
100 c = self.load_default_context()
107 c = self.load_default_context()
101 c.active = 'password'
108 c.active = 'password'
102 c.extern_type = c.user.extern_type
109 c.extern_type = c.user.extern_type
103
110
104 schema = user_schema.ChangePasswordSchema().bind(
111 schema = user_schema.ChangePasswordSchema().bind(
105 username=c.user.username)
112 username=c.user.username)
106
113
107 form = forms.Form(
114 form = forms.Form(
108 schema, buttons=(forms.buttons.save, forms.buttons.reset))
115 schema, buttons=(forms.buttons.save, forms.buttons.reset))
109
116
110 if c.extern_type != 'rhodecode':
117 if c.extern_type != 'rhodecode':
111 raise HTTPFound(self.request.route_path('my_account_password'))
118 raise HTTPFound(self.request.route_path('my_account_password'))
112
119
113 controls = self.request.POST.items()
120 controls = self.request.POST.items()
114 try:
121 try:
115 valid_data = form.validate(controls)
122 valid_data = form.validate(controls)
116 UserModel().update_user(c.user.user_id, **valid_data)
123 UserModel().update_user(c.user.user_id, **valid_data)
117 c.user.update_userdata(force_password_change=False)
124 c.user.update_userdata(force_password_change=False)
118 Session().commit()
125 Session().commit()
119 except forms.ValidationFailure as e:
126 except forms.ValidationFailure as e:
120 c.form = e
127 c.form = e
121 return self._get_template_context(c)
128 return self._get_template_context(c)
122
129
123 except Exception:
130 except Exception:
124 log.exception("Exception updating password")
131 log.exception("Exception updating password")
125 h.flash(_('Error occurred during update of user password'),
132 h.flash(_('Error occurred during update of user password'),
126 category='error')
133 category='error')
127 else:
134 else:
128 instance = c.auth_user.get_instance()
135 instance = c.auth_user.get_instance()
129 self.session.setdefault('rhodecode_user', {}).update(
136 self.session.setdefault('rhodecode_user', {}).update(
130 {'password': md5(instance.password)})
137 {'password': md5(instance.password)})
131 self.session.save()
138 self.session.save()
132 h.flash(_("Successfully updated password"), category='success')
139 h.flash(_("Successfully updated password"), category='success')
133
140
134 raise HTTPFound(self.request.route_path('my_account_password'))
141 raise HTTPFound(self.request.route_path('my_account_password'))
135
142
136 @LoginRequired()
143 @LoginRequired()
137 @NotAnonymous()
144 @NotAnonymous()
138 @view_config(
145 @view_config(
139 route_name='my_account_auth_tokens', request_method='GET',
146 route_name='my_account_auth_tokens', request_method='GET',
140 renderer='rhodecode:templates/admin/my_account/my_account.mako')
147 renderer='rhodecode:templates/admin/my_account/my_account.mako')
141 def my_account_auth_tokens(self):
148 def my_account_auth_tokens(self):
142 _ = self.request.translate
149 _ = self.request.translate
143
150
144 c = self.load_default_context()
151 c = self.load_default_context()
145 c.active = 'auth_tokens'
152 c.active = 'auth_tokens'
146
153
147 c.lifetime_values = [
154 c.lifetime_values = [
148 (str(-1), _('forever')),
155 (str(-1), _('forever')),
149 (str(5), _('5 minutes')),
156 (str(5), _('5 minutes')),
150 (str(60), _('1 hour')),
157 (str(60), _('1 hour')),
151 (str(60 * 24), _('1 day')),
158 (str(60 * 24), _('1 day')),
152 (str(60 * 24 * 30), _('1 month')),
159 (str(60 * 24 * 30), _('1 month')),
153 ]
160 ]
154 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
161 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
155 c.role_values = [
162 c.role_values = [
156 (x, AuthTokenModel.cls._get_role_name(x))
163 (x, AuthTokenModel.cls._get_role_name(x))
157 for x in AuthTokenModel.cls.ROLES]
164 for x in AuthTokenModel.cls.ROLES]
158 c.role_options = [(c.role_values, _("Role"))]
165 c.role_options = [(c.role_values, _("Role"))]
159 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
166 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
160 c.user.user_id, show_expired=True)
167 c.user.user_id, show_expired=True)
161 return self._get_template_context(c)
168 return self._get_template_context(c)
162
169
163 def maybe_attach_token_scope(self, token):
170 def maybe_attach_token_scope(self, token):
164 # implemented in EE edition
171 # implemented in EE edition
165 pass
172 pass
166
173
167 @LoginRequired()
174 @LoginRequired()
168 @NotAnonymous()
175 @NotAnonymous()
169 @CSRFRequired()
176 @CSRFRequired()
170 @view_config(
177 @view_config(
171 route_name='my_account_auth_tokens_add', request_method='POST',)
178 route_name='my_account_auth_tokens_add', request_method='POST',)
172 def my_account_auth_tokens_add(self):
179 def my_account_auth_tokens_add(self):
173 _ = self.request.translate
180 _ = self.request.translate
174 c = self.load_default_context()
181 c = self.load_default_context()
175
182
176 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
183 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
177 description = self.request.POST.get('description')
184 description = self.request.POST.get('description')
178 role = self.request.POST.get('role')
185 role = self.request.POST.get('role')
179
186
180 token = AuthTokenModel().create(
187 token = AuthTokenModel().create(
181 c.user.user_id, description, lifetime, role)
188 c.user.user_id, description, lifetime, role)
182 token_data = token.get_api_data()
189 token_data = token.get_api_data()
183
190
184 self.maybe_attach_token_scope(token)
191 self.maybe_attach_token_scope(token)
185 audit_logger.store_web(
192 audit_logger.store_web(
186 'user.edit.token.add', action_data={
193 'user.edit.token.add', action_data={
187 'data': {'token': token_data, 'user': 'self'}},
194 'data': {'token': token_data, 'user': 'self'}},
188 user=self._rhodecode_user, )
195 user=self._rhodecode_user, )
189 Session().commit()
196 Session().commit()
190
197
191 h.flash(_("Auth token successfully created"), category='success')
198 h.flash(_("Auth token successfully created"), category='success')
192 return HTTPFound(h.route_path('my_account_auth_tokens'))
199 return HTTPFound(h.route_path('my_account_auth_tokens'))
193
200
194 @LoginRequired()
201 @LoginRequired()
195 @NotAnonymous()
202 @NotAnonymous()
196 @CSRFRequired()
203 @CSRFRequired()
197 @view_config(
204 @view_config(
198 route_name='my_account_auth_tokens_delete', request_method='POST')
205 route_name='my_account_auth_tokens_delete', request_method='POST')
199 def my_account_auth_tokens_delete(self):
206 def my_account_auth_tokens_delete(self):
200 _ = self.request.translate
207 _ = self.request.translate
201 c = self.load_default_context()
208 c = self.load_default_context()
202
209
203 del_auth_token = self.request.POST.get('del_auth_token')
210 del_auth_token = self.request.POST.get('del_auth_token')
204
211
205 if del_auth_token:
212 if del_auth_token:
206 token = UserApiKeys.get_or_404(del_auth_token, pyramid_exc=True)
213 token = UserApiKeys.get_or_404(del_auth_token, pyramid_exc=True)
207 token_data = token.get_api_data()
214 token_data = token.get_api_data()
208
215
209 AuthTokenModel().delete(del_auth_token, c.user.user_id)
216 AuthTokenModel().delete(del_auth_token, c.user.user_id)
210 audit_logger.store_web(
217 audit_logger.store_web(
211 'user.edit.token.delete', action_data={
218 'user.edit.token.delete', action_data={
212 'data': {'token': token_data, 'user': 'self'}},
219 'data': {'token': token_data, 'user': 'self'}},
213 user=self._rhodecode_user,)
220 user=self._rhodecode_user,)
214 Session().commit()
221 Session().commit()
215 h.flash(_("Auth token successfully deleted"), category='success')
222 h.flash(_("Auth token successfully deleted"), category='success')
216
223
217 return HTTPFound(h.route_path('my_account_auth_tokens'))
224 return HTTPFound(h.route_path('my_account_auth_tokens'))
218
225
219 @LoginRequired()
226 @LoginRequired()
220 @NotAnonymous()
227 @NotAnonymous()
221 @view_config(
228 @view_config(
222 route_name='my_account_emails', request_method='GET',
229 route_name='my_account_emails', request_method='GET',
223 renderer='rhodecode:templates/admin/my_account/my_account.mako')
230 renderer='rhodecode:templates/admin/my_account/my_account.mako')
224 def my_account_emails(self):
231 def my_account_emails(self):
225 _ = self.request.translate
232 _ = self.request.translate
226
233
227 c = self.load_default_context()
234 c = self.load_default_context()
228 c.active = 'emails'
235 c.active = 'emails'
229
236
230 c.user_email_map = UserEmailMap.query()\
237 c.user_email_map = UserEmailMap.query()\
231 .filter(UserEmailMap.user == c.user).all()
238 .filter(UserEmailMap.user == c.user).all()
232 return self._get_template_context(c)
239 return self._get_template_context(c)
233
240
234 @LoginRequired()
241 @LoginRequired()
235 @NotAnonymous()
242 @NotAnonymous()
236 @CSRFRequired()
243 @CSRFRequired()
237 @view_config(
244 @view_config(
238 route_name='my_account_emails_add', request_method='POST')
245 route_name='my_account_emails_add', request_method='POST')
239 def my_account_emails_add(self):
246 def my_account_emails_add(self):
240 _ = self.request.translate
247 _ = self.request.translate
241 c = self.load_default_context()
248 c = self.load_default_context()
242
249
243 email = self.request.POST.get('new_email')
250 email = self.request.POST.get('new_email')
244
251
245 try:
252 try:
246 UserModel().add_extra_email(c.user.user_id, email)
253 UserModel().add_extra_email(c.user.user_id, email)
247 audit_logger.store_web(
254 audit_logger.store_web(
248 'user.edit.email.add', action_data={
255 'user.edit.email.add', action_data={
249 'data': {'email': email, 'user': 'self'}},
256 'data': {'email': email, 'user': 'self'}},
250 user=self._rhodecode_user,)
257 user=self._rhodecode_user,)
251
258
252 Session().commit()
259 Session().commit()
253 h.flash(_("Added new email address `%s` for user account") % email,
260 h.flash(_("Added new email address `%s` for user account") % email,
254 category='success')
261 category='success')
255 except formencode.Invalid as error:
262 except formencode.Invalid as error:
256 h.flash(h.escape(error.error_dict['email']), category='error')
263 h.flash(h.escape(error.error_dict['email']), category='error')
257 except Exception:
264 except Exception:
258 log.exception("Exception in my_account_emails")
265 log.exception("Exception in my_account_emails")
259 h.flash(_('An error occurred during email saving'),
266 h.flash(_('An error occurred during email saving'),
260 category='error')
267 category='error')
261 return HTTPFound(h.route_path('my_account_emails'))
268 return HTTPFound(h.route_path('my_account_emails'))
262
269
263 @LoginRequired()
270 @LoginRequired()
264 @NotAnonymous()
271 @NotAnonymous()
265 @CSRFRequired()
272 @CSRFRequired()
266 @view_config(
273 @view_config(
267 route_name='my_account_emails_delete', request_method='POST')
274 route_name='my_account_emails_delete', request_method='POST')
268 def my_account_emails_delete(self):
275 def my_account_emails_delete(self):
269 _ = self.request.translate
276 _ = self.request.translate
270 c = self.load_default_context()
277 c = self.load_default_context()
271
278
272 del_email_id = self.request.POST.get('del_email_id')
279 del_email_id = self.request.POST.get('del_email_id')
273 if del_email_id:
280 if del_email_id:
274 email = UserEmailMap.get_or_404(del_email_id, pyramid_exc=True).email
281 email = UserEmailMap.get_or_404(del_email_id, pyramid_exc=True).email
275 UserModel().delete_extra_email(c.user.user_id, del_email_id)
282 UserModel().delete_extra_email(c.user.user_id, del_email_id)
276 audit_logger.store_web(
283 audit_logger.store_web(
277 'user.edit.email.delete', action_data={
284 'user.edit.email.delete', action_data={
278 'data': {'email': email, 'user': 'self'}},
285 'data': {'email': email, 'user': 'self'}},
279 user=self._rhodecode_user,)
286 user=self._rhodecode_user,)
280 Session().commit()
287 Session().commit()
281 h.flash(_("Email successfully deleted"),
288 h.flash(_("Email successfully deleted"),
282 category='success')
289 category='success')
283 return HTTPFound(h.route_path('my_account_emails'))
290 return HTTPFound(h.route_path('my_account_emails'))
284
291
285 @LoginRequired()
292 @LoginRequired()
286 @NotAnonymous()
293 @NotAnonymous()
287 @CSRFRequired()
294 @CSRFRequired()
288 @view_config(
295 @view_config(
289 route_name='my_account_notifications_test_channelstream',
296 route_name='my_account_notifications_test_channelstream',
290 request_method='POST', renderer='json_ext')
297 request_method='POST', renderer='json_ext')
291 def my_account_notifications_test_channelstream(self):
298 def my_account_notifications_test_channelstream(self):
292 message = 'Test message sent via Channelstream by user: {}, on {}'.format(
299 message = 'Test message sent via Channelstream by user: {}, on {}'.format(
293 self._rhodecode_user.username, datetime.datetime.now())
300 self._rhodecode_user.username, datetime.datetime.now())
294 payload = {
301 payload = {
295 # 'channel': 'broadcast',
302 # 'channel': 'broadcast',
296 'type': 'message',
303 'type': 'message',
297 'timestamp': datetime.datetime.utcnow(),
304 'timestamp': datetime.datetime.utcnow(),
298 'user': 'system',
305 'user': 'system',
299 'pm_users': [self._rhodecode_user.username],
306 'pm_users': [self._rhodecode_user.username],
300 'message': {
307 'message': {
301 'message': message,
308 'message': message,
302 'level': 'info',
309 'level': 'info',
303 'topic': '/notifications'
310 'topic': '/notifications'
304 }
311 }
305 }
312 }
306
313
307 registry = self.request.registry
314 registry = self.request.registry
308 rhodecode_plugins = getattr(registry, 'rhodecode_plugins', {})
315 rhodecode_plugins = getattr(registry, 'rhodecode_plugins', {})
309 channelstream_config = rhodecode_plugins.get('channelstream', {})
316 channelstream_config = rhodecode_plugins.get('channelstream', {})
310
317
311 try:
318 try:
312 channelstream_request(channelstream_config, [payload], '/message')
319 channelstream_request(channelstream_config, [payload], '/message')
313 except ChannelstreamException as e:
320 except ChannelstreamException as e:
314 log.exception('Failed to send channelstream data')
321 log.exception('Failed to send channelstream data')
315 return {"response": 'ERROR: {}'.format(e.__class__.__name__)}
322 return {"response": 'ERROR: {}'.format(e.__class__.__name__)}
316 return {"response": 'Channelstream data sent. '
323 return {"response": 'Channelstream data sent. '
317 'You should see a new live message now.'}
324 'You should see a new live message now.'}
318
325
319 def _load_my_repos_data(self, watched=False):
326 def _load_my_repos_data(self, watched=False):
320 if watched:
327 if watched:
321 admin = False
328 admin = False
322 follows_repos = Session().query(UserFollowing)\
329 follows_repos = Session().query(UserFollowing)\
323 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
330 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
324 .options(joinedload(UserFollowing.follows_repository))\
331 .options(joinedload(UserFollowing.follows_repository))\
325 .all()
332 .all()
326 repo_list = [x.follows_repository for x in follows_repos]
333 repo_list = [x.follows_repository for x in follows_repos]
327 else:
334 else:
328 admin = True
335 admin = True
329 repo_list = Repository.get_all_repos(
336 repo_list = Repository.get_all_repos(
330 user_id=self._rhodecode_user.user_id)
337 user_id=self._rhodecode_user.user_id)
331 repo_list = RepoList(repo_list, perm_set=[
338 repo_list = RepoList(repo_list, perm_set=[
332 'repository.read', 'repository.write', 'repository.admin'])
339 'repository.read', 'repository.write', 'repository.admin'])
333
340
334 repos_data = RepoModel().get_repos_as_dict(
341 repos_data = RepoModel().get_repos_as_dict(
335 repo_list=repo_list, admin=admin)
342 repo_list=repo_list, admin=admin)
336 # json used to render the grid
343 # json used to render the grid
337 return json.dumps(repos_data)
344 return json.dumps(repos_data)
338
345
339 @LoginRequired()
346 @LoginRequired()
340 @NotAnonymous()
347 @NotAnonymous()
341 @view_config(
348 @view_config(
342 route_name='my_account_repos', request_method='GET',
349 route_name='my_account_repos', request_method='GET',
343 renderer='rhodecode:templates/admin/my_account/my_account.mako')
350 renderer='rhodecode:templates/admin/my_account/my_account.mako')
344 def my_account_repos(self):
351 def my_account_repos(self):
345 c = self.load_default_context()
352 c = self.load_default_context()
346 c.active = 'repos'
353 c.active = 'repos'
347
354
348 # json used to render the grid
355 # json used to render the grid
349 c.data = self._load_my_repos_data()
356 c.data = self._load_my_repos_data()
350 return self._get_template_context(c)
357 return self._get_template_context(c)
351
358
352 @LoginRequired()
359 @LoginRequired()
353 @NotAnonymous()
360 @NotAnonymous()
354 @view_config(
361 @view_config(
355 route_name='my_account_watched', request_method='GET',
362 route_name='my_account_watched', request_method='GET',
356 renderer='rhodecode:templates/admin/my_account/my_account.mako')
363 renderer='rhodecode:templates/admin/my_account/my_account.mako')
357 def my_account_watched(self):
364 def my_account_watched(self):
358 c = self.load_default_context()
365 c = self.load_default_context()
359 c.active = 'watched'
366 c.active = 'watched'
360
367
361 # json used to render the grid
368 # json used to render the grid
362 c.data = self._load_my_repos_data(watched=True)
369 c.data = self._load_my_repos_data(watched=True)
363 return self._get_template_context(c)
370 return self._get_template_context(c)
364
371
365 @LoginRequired()
372 @LoginRequired()
366 @NotAnonymous()
373 @NotAnonymous()
367 @view_config(
374 @view_config(
368 route_name='my_account_perms', request_method='GET',
375 route_name='my_account_perms', request_method='GET',
369 renderer='rhodecode:templates/admin/my_account/my_account.mako')
376 renderer='rhodecode:templates/admin/my_account/my_account.mako')
370 def my_account_perms(self):
377 def my_account_perms(self):
371 c = self.load_default_context()
378 c = self.load_default_context()
372 c.active = 'perms'
379 c.active = 'perms'
373
380
374 c.perm_user = c.auth_user
381 c.perm_user = c.auth_user
375 return self._get_template_context(c)
382 return self._get_template_context(c)
376
383
377 @LoginRequired()
384 @LoginRequired()
378 @NotAnonymous()
385 @NotAnonymous()
379 @view_config(
386 @view_config(
380 route_name='my_account_notifications', request_method='GET',
387 route_name='my_account_notifications', request_method='GET',
381 renderer='rhodecode:templates/admin/my_account/my_account.mako')
388 renderer='rhodecode:templates/admin/my_account/my_account.mako')
382 def my_notifications(self):
389 def my_notifications(self):
383 c = self.load_default_context()
390 c = self.load_default_context()
384 c.active = 'notifications'
391 c.active = 'notifications'
385
392
386 return self._get_template_context(c)
393 return self._get_template_context(c)
387
394
388 @LoginRequired()
395 @LoginRequired()
389 @NotAnonymous()
396 @NotAnonymous()
390 @CSRFRequired()
397 @CSRFRequired()
391 @view_config(
398 @view_config(
392 route_name='my_account_notifications_toggle_visibility',
399 route_name='my_account_notifications_toggle_visibility',
393 request_method='POST', renderer='json_ext')
400 request_method='POST', renderer='json_ext')
394 def my_notifications_toggle_visibility(self):
401 def my_notifications_toggle_visibility(self):
395 user = self._rhodecode_db_user
402 user = self._rhodecode_db_user
396 new_status = not user.user_data.get('notification_status', True)
403 new_status = not user.user_data.get('notification_status', True)
397 user.update_userdata(notification_status=new_status)
404 user.update_userdata(notification_status=new_status)
398 Session().commit()
405 Session().commit()
399 return user.user_data['notification_status'] No newline at end of file
406 return user.user_data['notification_status']
407
408 @LoginRequired()
409 @NotAnonymous()
410 @view_config(
411 route_name='my_account_edit',
412 request_method='GET',
413 renderer='rhodecode:templates/admin/my_account/my_account.mako')
414 def my_account_edit(self):
415 c = self.load_default_context()
416 c.active = 'profile_edit'
417
418 c.perm_user = c.auth_user
419 c.extern_type = c.user.extern_type
420 c.extern_name = c.user.extern_name
421
422 defaults = c.user.get_dict()
423
424 data = render('rhodecode:templates/admin/my_account/my_account.mako',
425 self._get_template_context(c), self.request)
426 html = formencode.htmlfill.render(
427 data,
428 defaults=defaults,
429 encoding="UTF-8",
430 force_defaults=False
431 )
432 return Response(html)
433
434 @LoginRequired()
435 @NotAnonymous()
436 @CSRFRequired()
437 @view_config(
438 route_name='my_account_update',
439 request_method='POST',
440 renderer='rhodecode:templates/admin/my_account/my_account.mako')
441 def my_account_update(self):
442 _ = self.request.translate
443 c = self.load_default_context()
444 c.active = 'profile_edit'
445
446 c.perm_user = c.auth_user
447 c.extern_type = c.user.extern_type
448 c.extern_name = c.user.extern_name
449
450 _form = UserForm(edit=True,
451 old_data={'user_id': self._rhodecode_user.user_id,
452 'email': self._rhodecode_user.email})()
453 form_result = {}
454 try:
455 post_data = dict(self.request.POST)
456 post_data['new_password'] = ''
457 post_data['password_confirmation'] = ''
458 form_result = _form.to_python(post_data)
459 # skip updating those attrs for my account
460 skip_attrs = ['admin', 'active', 'extern_type', 'extern_name',
461 'new_password', 'password_confirmation']
462 # TODO: plugin should define if username can be updated
463 if c.extern_type != "rhodecode":
464 # forbid updating username for external accounts
465 skip_attrs.append('username')
466
467 UserModel().update_user(
468 self._rhodecode_user.user_id, skip_attrs=skip_attrs,
469 **form_result)
470 h.flash(_('Your account was updated successfully'),
471 category='success')
472 Session().commit()
473
474 except formencode.Invalid as errors:
475 data = render(
476 'rhodecode:templates/admin/my_account/my_account.mako',
477 self._get_template_context(c), self.request)
478
479 html = formencode.htmlfill.render(
480 data,
481 defaults=errors.value,
482 errors=errors.error_dict or {},
483 prefix_error=False,
484 encoding="UTF-8",
485 force_defaults=False)
486 return Response(html)
487
488 except Exception:
489 log.exception("Exception updating user")
490 h.flash(_('Error occurred during update of user %s')
491 % form_result.get('username'), category='error')
492 raise HTTPFound(h.route_path('my_account_profile'))
493
494 raise HTTPFound(h.route_path('my_account_profile'))
495
496 def _get_pull_requests_list(self, statuses):
497 draw, start, limit = self._extract_chunk(self.request)
498 search_q, order_by, order_dir = self._extract_ordering(self.request)
499 _render = PartialRenderer('data_table/_dt_elements.mako')
500
501 pull_requests = PullRequestModel().get_im_participating_in(
502 user_id=self._rhodecode_user.user_id,
503 statuses=statuses,
504 offset=start, length=limit, order_by=order_by,
505 order_dir=order_dir)
506
507 pull_requests_total_count = PullRequestModel().count_im_participating_in(
508 user_id=self._rhodecode_user.user_id, statuses=statuses)
509
510 data = []
511 comments_model = CommentsModel()
512 for pr in pull_requests:
513 repo_id = pr.target_repo_id
514 comments = comments_model.get_all_comments(
515 repo_id, pull_request=pr)
516 owned = pr.user_id == self._rhodecode_user.user_id
517
518 data.append({
519 'target_repo': _render('pullrequest_target_repo',
520 pr.target_repo.repo_name),
521 'name': _render('pullrequest_name',
522 pr.pull_request_id, pr.target_repo.repo_name,
523 short=True),
524 'name_raw': pr.pull_request_id,
525 'status': _render('pullrequest_status',
526 pr.calculated_review_status()),
527 'title': _render(
528 'pullrequest_title', pr.title, pr.description),
529 'description': h.escape(pr.description),
530 'updated_on': _render('pullrequest_updated_on',
531 h.datetime_to_time(pr.updated_on)),
532 'updated_on_raw': h.datetime_to_time(pr.updated_on),
533 'created_on': _render('pullrequest_updated_on',
534 h.datetime_to_time(pr.created_on)),
535 'created_on_raw': h.datetime_to_time(pr.created_on),
536 'author': _render('pullrequest_author',
537 pr.author.full_contact, ),
538 'author_raw': pr.author.full_name,
539 'comments': _render('pullrequest_comments', len(comments)),
540 'comments_raw': len(comments),
541 'closed': pr.is_closed(),
542 'owned': owned
543 })
544
545 # json used to render the grid
546 data = ({
547 'draw': draw,
548 'data': data,
549 'recordsTotal': pull_requests_total_count,
550 'recordsFiltered': pull_requests_total_count,
551 })
552 return data
553
554 @LoginRequired()
555 @NotAnonymous()
556 @view_config(
557 route_name='my_account_pullrequests',
558 request_method='GET',
559 renderer='rhodecode:templates/admin/my_account/my_account.mako')
560 def my_account_pullrequests(self):
561 c = self.load_default_context()
562 c.active = 'pullrequests'
563 req_get = self.request.GET
564
565 c.closed = str2bool(req_get.get('pr_show_closed'))
566
567 return self._get_template_context(c)
568
569 @LoginRequired()
570 @NotAnonymous()
571 @view_config(
572 route_name='my_account_pullrequests_data',
573 request_method='GET', renderer='json_ext')
574 def my_account_pullrequests_data(self):
575 req_get = self.request.GET
576 closed = str2bool(req_get.get('closed'))
577
578 statuses = [PullRequest.STATUS_NEW, PullRequest.STATUS_OPEN]
579 if closed:
580 statuses += [PullRequest.STATUS_CLOSED]
581
582 data = self._get_pull_requests_list(statuses=statuses)
583 return data
584
@@ -1,912 +1,904 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2017 RhodeCode GmbH
3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Routes configuration
22 Routes configuration
23
23
24 The more specific and detailed routes should be defined first so they
24 The more specific and detailed routes should be defined first so they
25 may take precedent over the more generic routes. For more information
25 may take precedent over the more generic routes. For more information
26 refer to the routes manual at http://routes.groovie.org/docs/
26 refer to the routes manual at http://routes.groovie.org/docs/
27
27
28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
29 and _route_name variable which uses some of stored naming here to do redirects.
29 and _route_name variable which uses some of stored naming here to do redirects.
30 """
30 """
31 import os
31 import os
32 import re
32 import re
33 from routes import Mapper
33 from routes import Mapper
34
34
35 # prefix for non repository related links needs to be prefixed with `/`
35 # prefix for non repository related links needs to be prefixed with `/`
36 ADMIN_PREFIX = '/_admin'
36 ADMIN_PREFIX = '/_admin'
37 STATIC_FILE_PREFIX = '/_static'
37 STATIC_FILE_PREFIX = '/_static'
38
38
39 # Default requirements for URL parts
39 # Default requirements for URL parts
40 URL_NAME_REQUIREMENTS = {
40 URL_NAME_REQUIREMENTS = {
41 # group name can have a slash in them, but they must not end with a slash
41 # group name can have a slash in them, but they must not end with a slash
42 'group_name': r'.*?[^/]',
42 'group_name': r'.*?[^/]',
43 'repo_group_name': r'.*?[^/]',
43 'repo_group_name': r'.*?[^/]',
44 # repo names can have a slash in them, but they must not end with a slash
44 # repo names can have a slash in them, but they must not end with a slash
45 'repo_name': r'.*?[^/]',
45 'repo_name': r'.*?[^/]',
46 # file path eats up everything at the end
46 # file path eats up everything at the end
47 'f_path': r'.*',
47 'f_path': r'.*',
48 # reference types
48 # reference types
49 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
49 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
50 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
50 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
51 }
51 }
52
52
53
53
54 def add_route_requirements(route_path, requirements):
54 def add_route_requirements(route_path, requirements):
55 """
55 """
56 Adds regex requirements to pyramid routes using a mapping dict
56 Adds regex requirements to pyramid routes using a mapping dict
57
57
58 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
58 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
59 '/{action}/{id:\d+}'
59 '/{action}/{id:\d+}'
60
60
61 """
61 """
62 for key, regex in requirements.items():
62 for key, regex in requirements.items():
63 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
63 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
64 return route_path
64 return route_path
65
65
66
66
67 class JSRoutesMapper(Mapper):
67 class JSRoutesMapper(Mapper):
68 """
68 """
69 Wrapper for routes.Mapper to make pyroutes compatible url definitions
69 Wrapper for routes.Mapper to make pyroutes compatible url definitions
70 """
70 """
71 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
71 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
72 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
72 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
73 def __init__(self, *args, **kw):
73 def __init__(self, *args, **kw):
74 super(JSRoutesMapper, self).__init__(*args, **kw)
74 super(JSRoutesMapper, self).__init__(*args, **kw)
75 self._jsroutes = []
75 self._jsroutes = []
76
76
77 def connect(self, *args, **kw):
77 def connect(self, *args, **kw):
78 """
78 """
79 Wrapper for connect to take an extra argument jsroute=True
79 Wrapper for connect to take an extra argument jsroute=True
80
80
81 :param jsroute: boolean, if True will add the route to the pyroutes list
81 :param jsroute: boolean, if True will add the route to the pyroutes list
82 """
82 """
83 if kw.pop('jsroute', False):
83 if kw.pop('jsroute', False):
84 if not self._named_route_regex.match(args[0]):
84 if not self._named_route_regex.match(args[0]):
85 raise Exception('only named routes can be added to pyroutes')
85 raise Exception('only named routes can be added to pyroutes')
86 self._jsroutes.append(args[0])
86 self._jsroutes.append(args[0])
87
87
88 super(JSRoutesMapper, self).connect(*args, **kw)
88 super(JSRoutesMapper, self).connect(*args, **kw)
89
89
90 def _extract_route_information(self, route):
90 def _extract_route_information(self, route):
91 """
91 """
92 Convert a route into tuple(name, path, args), eg:
92 Convert a route into tuple(name, path, args), eg:
93 ('show_user', '/profile/%(username)s', ['username'])
93 ('show_user', '/profile/%(username)s', ['username'])
94 """
94 """
95 routepath = route.routepath
95 routepath = route.routepath
96 def replace(matchobj):
96 def replace(matchobj):
97 if matchobj.group(1):
97 if matchobj.group(1):
98 return "%%(%s)s" % matchobj.group(1).split(':')[0]
98 return "%%(%s)s" % matchobj.group(1).split(':')[0]
99 else:
99 else:
100 return "%%(%s)s" % matchobj.group(2)
100 return "%%(%s)s" % matchobj.group(2)
101
101
102 routepath = self._argument_prog.sub(replace, routepath)
102 routepath = self._argument_prog.sub(replace, routepath)
103 return (
103 return (
104 route.name,
104 route.name,
105 routepath,
105 routepath,
106 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
106 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
107 for arg in self._argument_prog.findall(route.routepath)]
107 for arg in self._argument_prog.findall(route.routepath)]
108 )
108 )
109
109
110 def jsroutes(self):
110 def jsroutes(self):
111 """
111 """
112 Return a list of pyroutes.js compatible routes
112 Return a list of pyroutes.js compatible routes
113 """
113 """
114 for route_name in self._jsroutes:
114 for route_name in self._jsroutes:
115 yield self._extract_route_information(self._routenames[route_name])
115 yield self._extract_route_information(self._routenames[route_name])
116
116
117
117
118 def make_map(config):
118 def make_map(config):
119 """Create, configure and return the routes Mapper"""
119 """Create, configure and return the routes Mapper"""
120 rmap = JSRoutesMapper(
120 rmap = JSRoutesMapper(
121 directory=config['pylons.paths']['controllers'],
121 directory=config['pylons.paths']['controllers'],
122 always_scan=config['debug'])
122 always_scan=config['debug'])
123 rmap.minimization = False
123 rmap.minimization = False
124 rmap.explicit = False
124 rmap.explicit = False
125
125
126 from rhodecode.lib.utils2 import str2bool
126 from rhodecode.lib.utils2 import str2bool
127 from rhodecode.model import repo, repo_group
127 from rhodecode.model import repo, repo_group
128
128
129 def check_repo(environ, match_dict):
129 def check_repo(environ, match_dict):
130 """
130 """
131 check for valid repository for proper 404 handling
131 check for valid repository for proper 404 handling
132
132
133 :param environ:
133 :param environ:
134 :param match_dict:
134 :param match_dict:
135 """
135 """
136 repo_name = match_dict.get('repo_name')
136 repo_name = match_dict.get('repo_name')
137
137
138 if match_dict.get('f_path'):
138 if match_dict.get('f_path'):
139 # fix for multiple initial slashes that causes errors
139 # fix for multiple initial slashes that causes errors
140 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
140 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
141 repo_model = repo.RepoModel()
141 repo_model = repo.RepoModel()
142 by_name_match = repo_model.get_by_repo_name(repo_name)
142 by_name_match = repo_model.get_by_repo_name(repo_name)
143 # if we match quickly from database, short circuit the operation,
143 # if we match quickly from database, short circuit the operation,
144 # and validate repo based on the type.
144 # and validate repo based on the type.
145 if by_name_match:
145 if by_name_match:
146 return True
146 return True
147
147
148 by_id_match = repo_model.get_repo_by_id(repo_name)
148 by_id_match = repo_model.get_repo_by_id(repo_name)
149 if by_id_match:
149 if by_id_match:
150 repo_name = by_id_match.repo_name
150 repo_name = by_id_match.repo_name
151 match_dict['repo_name'] = repo_name
151 match_dict['repo_name'] = repo_name
152 return True
152 return True
153
153
154 return False
154 return False
155
155
156 def check_group(environ, match_dict):
156 def check_group(environ, match_dict):
157 """
157 """
158 check for valid repository group path for proper 404 handling
158 check for valid repository group path for proper 404 handling
159
159
160 :param environ:
160 :param environ:
161 :param match_dict:
161 :param match_dict:
162 """
162 """
163 repo_group_name = match_dict.get('group_name')
163 repo_group_name = match_dict.get('group_name')
164 repo_group_model = repo_group.RepoGroupModel()
164 repo_group_model = repo_group.RepoGroupModel()
165 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
165 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
166 if by_name_match:
166 if by_name_match:
167 return True
167 return True
168
168
169 return False
169 return False
170
170
171 def check_user_group(environ, match_dict):
171 def check_user_group(environ, match_dict):
172 """
172 """
173 check for valid user group for proper 404 handling
173 check for valid user group for proper 404 handling
174
174
175 :param environ:
175 :param environ:
176 :param match_dict:
176 :param match_dict:
177 """
177 """
178 return True
178 return True
179
179
180 def check_int(environ, match_dict):
180 def check_int(environ, match_dict):
181 return match_dict.get('id').isdigit()
181 return match_dict.get('id').isdigit()
182
182
183
183
184 #==========================================================================
184 #==========================================================================
185 # CUSTOM ROUTES HERE
185 # CUSTOM ROUTES HERE
186 #==========================================================================
186 #==========================================================================
187
187
188 # ping and pylons error test
188 # ping and pylons error test
189 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
189 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
190 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
190 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
191
191
192 # ADMIN REPOSITORY ROUTES
192 # ADMIN REPOSITORY ROUTES
193 with rmap.submapper(path_prefix=ADMIN_PREFIX,
193 with rmap.submapper(path_prefix=ADMIN_PREFIX,
194 controller='admin/repos') as m:
194 controller='admin/repos') as m:
195 m.connect('repos', '/repos',
195 m.connect('repos', '/repos',
196 action='create', conditions={'method': ['POST']})
196 action='create', conditions={'method': ['POST']})
197 m.connect('repos', '/repos',
197 m.connect('repos', '/repos',
198 action='index', conditions={'method': ['GET']})
198 action='index', conditions={'method': ['GET']})
199 m.connect('new_repo', '/create_repository', jsroute=True,
199 m.connect('new_repo', '/create_repository', jsroute=True,
200 action='create_repository', conditions={'method': ['GET']})
200 action='create_repository', conditions={'method': ['GET']})
201 m.connect('delete_repo', '/repos/{repo_name}',
201 m.connect('delete_repo', '/repos/{repo_name}',
202 action='delete', conditions={'method': ['DELETE']},
202 action='delete', conditions={'method': ['DELETE']},
203 requirements=URL_NAME_REQUIREMENTS)
203 requirements=URL_NAME_REQUIREMENTS)
204 m.connect('repo', '/repos/{repo_name}',
204 m.connect('repo', '/repos/{repo_name}',
205 action='show', conditions={'method': ['GET'],
205 action='show', conditions={'method': ['GET'],
206 'function': check_repo},
206 'function': check_repo},
207 requirements=URL_NAME_REQUIREMENTS)
207 requirements=URL_NAME_REQUIREMENTS)
208
208
209 # ADMIN REPOSITORY GROUPS ROUTES
209 # ADMIN REPOSITORY GROUPS ROUTES
210 with rmap.submapper(path_prefix=ADMIN_PREFIX,
210 with rmap.submapper(path_prefix=ADMIN_PREFIX,
211 controller='admin/repo_groups') as m:
211 controller='admin/repo_groups') as m:
212 m.connect('repo_groups', '/repo_groups',
212 m.connect('repo_groups', '/repo_groups',
213 action='create', conditions={'method': ['POST']})
213 action='create', conditions={'method': ['POST']})
214 m.connect('repo_groups', '/repo_groups',
214 m.connect('repo_groups', '/repo_groups',
215 action='index', conditions={'method': ['GET']})
215 action='index', conditions={'method': ['GET']})
216 m.connect('new_repo_group', '/repo_groups/new',
216 m.connect('new_repo_group', '/repo_groups/new',
217 action='new', conditions={'method': ['GET']})
217 action='new', conditions={'method': ['GET']})
218 m.connect('update_repo_group', '/repo_groups/{group_name}',
218 m.connect('update_repo_group', '/repo_groups/{group_name}',
219 action='update', conditions={'method': ['PUT'],
219 action='update', conditions={'method': ['PUT'],
220 'function': check_group},
220 'function': check_group},
221 requirements=URL_NAME_REQUIREMENTS)
221 requirements=URL_NAME_REQUIREMENTS)
222
222
223 # EXTRAS REPO GROUP ROUTES
223 # EXTRAS REPO GROUP ROUTES
224 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
224 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
225 action='edit',
225 action='edit',
226 conditions={'method': ['GET'], 'function': check_group},
226 conditions={'method': ['GET'], 'function': check_group},
227 requirements=URL_NAME_REQUIREMENTS)
227 requirements=URL_NAME_REQUIREMENTS)
228 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
228 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
229 action='edit',
229 action='edit',
230 conditions={'method': ['PUT'], 'function': check_group},
230 conditions={'method': ['PUT'], 'function': check_group},
231 requirements=URL_NAME_REQUIREMENTS)
231 requirements=URL_NAME_REQUIREMENTS)
232
232
233 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
233 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
234 action='edit_repo_group_advanced',
234 action='edit_repo_group_advanced',
235 conditions={'method': ['GET'], 'function': check_group},
235 conditions={'method': ['GET'], 'function': check_group},
236 requirements=URL_NAME_REQUIREMENTS)
236 requirements=URL_NAME_REQUIREMENTS)
237 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
237 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
238 action='edit_repo_group_advanced',
238 action='edit_repo_group_advanced',
239 conditions={'method': ['PUT'], 'function': check_group},
239 conditions={'method': ['PUT'], 'function': check_group},
240 requirements=URL_NAME_REQUIREMENTS)
240 requirements=URL_NAME_REQUIREMENTS)
241
241
242 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
242 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
243 action='edit_repo_group_perms',
243 action='edit_repo_group_perms',
244 conditions={'method': ['GET'], 'function': check_group},
244 conditions={'method': ['GET'], 'function': check_group},
245 requirements=URL_NAME_REQUIREMENTS)
245 requirements=URL_NAME_REQUIREMENTS)
246 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
246 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
247 action='update_perms',
247 action='update_perms',
248 conditions={'method': ['PUT'], 'function': check_group},
248 conditions={'method': ['PUT'], 'function': check_group},
249 requirements=URL_NAME_REQUIREMENTS)
249 requirements=URL_NAME_REQUIREMENTS)
250
250
251 m.connect('delete_repo_group', '/repo_groups/{group_name}',
251 m.connect('delete_repo_group', '/repo_groups/{group_name}',
252 action='delete', conditions={'method': ['DELETE'],
252 action='delete', conditions={'method': ['DELETE'],
253 'function': check_group},
253 'function': check_group},
254 requirements=URL_NAME_REQUIREMENTS)
254 requirements=URL_NAME_REQUIREMENTS)
255
255
256 # ADMIN USER ROUTES
256 # ADMIN USER ROUTES
257 with rmap.submapper(path_prefix=ADMIN_PREFIX,
257 with rmap.submapper(path_prefix=ADMIN_PREFIX,
258 controller='admin/users') as m:
258 controller='admin/users') as m:
259 m.connect('users', '/users',
259 m.connect('users', '/users',
260 action='create', conditions={'method': ['POST']})
260 action='create', conditions={'method': ['POST']})
261 m.connect('new_user', '/users/new',
261 m.connect('new_user', '/users/new',
262 action='new', conditions={'method': ['GET']})
262 action='new', conditions={'method': ['GET']})
263 m.connect('update_user', '/users/{user_id}',
263 m.connect('update_user', '/users/{user_id}',
264 action='update', conditions={'method': ['PUT']})
264 action='update', conditions={'method': ['PUT']})
265 m.connect('delete_user', '/users/{user_id}',
265 m.connect('delete_user', '/users/{user_id}',
266 action='delete', conditions={'method': ['DELETE']})
266 action='delete', conditions={'method': ['DELETE']})
267 m.connect('edit_user', '/users/{user_id}/edit',
267 m.connect('edit_user', '/users/{user_id}/edit',
268 action='edit', conditions={'method': ['GET']}, jsroute=True)
268 action='edit', conditions={'method': ['GET']}, jsroute=True)
269 m.connect('user', '/users/{user_id}',
269 m.connect('user', '/users/{user_id}',
270 action='show', conditions={'method': ['GET']})
270 action='show', conditions={'method': ['GET']})
271 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
271 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
272 action='reset_password', conditions={'method': ['POST']})
272 action='reset_password', conditions={'method': ['POST']})
273 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
273 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
274 action='create_personal_repo_group', conditions={'method': ['POST']})
274 action='create_personal_repo_group', conditions={'method': ['POST']})
275
275
276 # EXTRAS USER ROUTES
276 # EXTRAS USER ROUTES
277 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
277 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
278 action='edit_advanced', conditions={'method': ['GET']})
278 action='edit_advanced', conditions={'method': ['GET']})
279 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
279 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
280 action='update_advanced', conditions={'method': ['PUT']})
280 action='update_advanced', conditions={'method': ['PUT']})
281
281
282 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
282 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
283 action='edit_global_perms', conditions={'method': ['GET']})
283 action='edit_global_perms', conditions={'method': ['GET']})
284 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
284 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
285 action='update_global_perms', conditions={'method': ['PUT']})
285 action='update_global_perms', conditions={'method': ['PUT']})
286
286
287 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
287 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
288 action='edit_perms_summary', conditions={'method': ['GET']})
288 action='edit_perms_summary', conditions={'method': ['GET']})
289
289
290
290
291 # ADMIN USER GROUPS REST ROUTES
291 # ADMIN USER GROUPS REST ROUTES
292 with rmap.submapper(path_prefix=ADMIN_PREFIX,
292 with rmap.submapper(path_prefix=ADMIN_PREFIX,
293 controller='admin/user_groups') as m:
293 controller='admin/user_groups') as m:
294 m.connect('users_groups', '/user_groups',
294 m.connect('users_groups', '/user_groups',
295 action='create', conditions={'method': ['POST']})
295 action='create', conditions={'method': ['POST']})
296 m.connect('users_groups', '/user_groups',
296 m.connect('users_groups', '/user_groups',
297 action='index', conditions={'method': ['GET']})
297 action='index', conditions={'method': ['GET']})
298 m.connect('new_users_group', '/user_groups/new',
298 m.connect('new_users_group', '/user_groups/new',
299 action='new', conditions={'method': ['GET']})
299 action='new', conditions={'method': ['GET']})
300 m.connect('update_users_group', '/user_groups/{user_group_id}',
300 m.connect('update_users_group', '/user_groups/{user_group_id}',
301 action='update', conditions={'method': ['PUT']})
301 action='update', conditions={'method': ['PUT']})
302 m.connect('delete_users_group', '/user_groups/{user_group_id}',
302 m.connect('delete_users_group', '/user_groups/{user_group_id}',
303 action='delete', conditions={'method': ['DELETE']})
303 action='delete', conditions={'method': ['DELETE']})
304 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
304 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
305 action='edit', conditions={'method': ['GET']},
305 action='edit', conditions={'method': ['GET']},
306 function=check_user_group)
306 function=check_user_group)
307
307
308 # EXTRAS USER GROUP ROUTES
308 # EXTRAS USER GROUP ROUTES
309 m.connect('edit_user_group_global_perms',
309 m.connect('edit_user_group_global_perms',
310 '/user_groups/{user_group_id}/edit/global_permissions',
310 '/user_groups/{user_group_id}/edit/global_permissions',
311 action='edit_global_perms', conditions={'method': ['GET']})
311 action='edit_global_perms', conditions={'method': ['GET']})
312 m.connect('edit_user_group_global_perms',
312 m.connect('edit_user_group_global_perms',
313 '/user_groups/{user_group_id}/edit/global_permissions',
313 '/user_groups/{user_group_id}/edit/global_permissions',
314 action='update_global_perms', conditions={'method': ['PUT']})
314 action='update_global_perms', conditions={'method': ['PUT']})
315 m.connect('edit_user_group_perms_summary',
315 m.connect('edit_user_group_perms_summary',
316 '/user_groups/{user_group_id}/edit/permissions_summary',
316 '/user_groups/{user_group_id}/edit/permissions_summary',
317 action='edit_perms_summary', conditions={'method': ['GET']})
317 action='edit_perms_summary', conditions={'method': ['GET']})
318
318
319 m.connect('edit_user_group_perms',
319 m.connect('edit_user_group_perms',
320 '/user_groups/{user_group_id}/edit/permissions',
320 '/user_groups/{user_group_id}/edit/permissions',
321 action='edit_perms', conditions={'method': ['GET']})
321 action='edit_perms', conditions={'method': ['GET']})
322 m.connect('edit_user_group_perms',
322 m.connect('edit_user_group_perms',
323 '/user_groups/{user_group_id}/edit/permissions',
323 '/user_groups/{user_group_id}/edit/permissions',
324 action='update_perms', conditions={'method': ['PUT']})
324 action='update_perms', conditions={'method': ['PUT']})
325
325
326 m.connect('edit_user_group_advanced',
326 m.connect('edit_user_group_advanced',
327 '/user_groups/{user_group_id}/edit/advanced',
327 '/user_groups/{user_group_id}/edit/advanced',
328 action='edit_advanced', conditions={'method': ['GET']})
328 action='edit_advanced', conditions={'method': ['GET']})
329
329
330 m.connect('edit_user_group_advanced_sync',
330 m.connect('edit_user_group_advanced_sync',
331 '/user_groups/{user_group_id}/edit/advanced/sync',
331 '/user_groups/{user_group_id}/edit/advanced/sync',
332 action='edit_advanced_set_synchronization', conditions={'method': ['POST']})
332 action='edit_advanced_set_synchronization', conditions={'method': ['POST']})
333
333
334 m.connect('edit_user_group_members',
334 m.connect('edit_user_group_members',
335 '/user_groups/{user_group_id}/edit/members', jsroute=True,
335 '/user_groups/{user_group_id}/edit/members', jsroute=True,
336 action='user_group_members', conditions={'method': ['GET']})
336 action='user_group_members', conditions={'method': ['GET']})
337
337
338 # ADMIN PERMISSIONS ROUTES
338 # ADMIN PERMISSIONS ROUTES
339 with rmap.submapper(path_prefix=ADMIN_PREFIX,
339 with rmap.submapper(path_prefix=ADMIN_PREFIX,
340 controller='admin/permissions') as m:
340 controller='admin/permissions') as m:
341 m.connect('admin_permissions_application', '/permissions/application',
341 m.connect('admin_permissions_application', '/permissions/application',
342 action='permission_application_update', conditions={'method': ['POST']})
342 action='permission_application_update', conditions={'method': ['POST']})
343 m.connect('admin_permissions_application', '/permissions/application',
343 m.connect('admin_permissions_application', '/permissions/application',
344 action='permission_application', conditions={'method': ['GET']})
344 action='permission_application', conditions={'method': ['GET']})
345
345
346 m.connect('admin_permissions_global', '/permissions/global',
346 m.connect('admin_permissions_global', '/permissions/global',
347 action='permission_global_update', conditions={'method': ['POST']})
347 action='permission_global_update', conditions={'method': ['POST']})
348 m.connect('admin_permissions_global', '/permissions/global',
348 m.connect('admin_permissions_global', '/permissions/global',
349 action='permission_global', conditions={'method': ['GET']})
349 action='permission_global', conditions={'method': ['GET']})
350
350
351 m.connect('admin_permissions_object', '/permissions/object',
351 m.connect('admin_permissions_object', '/permissions/object',
352 action='permission_objects_update', conditions={'method': ['POST']})
352 action='permission_objects_update', conditions={'method': ['POST']})
353 m.connect('admin_permissions_object', '/permissions/object',
353 m.connect('admin_permissions_object', '/permissions/object',
354 action='permission_objects', conditions={'method': ['GET']})
354 action='permission_objects', conditions={'method': ['GET']})
355
355
356 m.connect('admin_permissions_ips', '/permissions/ips',
356 m.connect('admin_permissions_ips', '/permissions/ips',
357 action='permission_ips', conditions={'method': ['POST']})
357 action='permission_ips', conditions={'method': ['POST']})
358 m.connect('admin_permissions_ips', '/permissions/ips',
358 m.connect('admin_permissions_ips', '/permissions/ips',
359 action='permission_ips', conditions={'method': ['GET']})
359 action='permission_ips', conditions={'method': ['GET']})
360
360
361 m.connect('admin_permissions_overview', '/permissions/overview',
361 m.connect('admin_permissions_overview', '/permissions/overview',
362 action='permission_perms', conditions={'method': ['GET']})
362 action='permission_perms', conditions={'method': ['GET']})
363
363
364 # ADMIN DEFAULTS REST ROUTES
364 # ADMIN DEFAULTS REST ROUTES
365 with rmap.submapper(path_prefix=ADMIN_PREFIX,
365 with rmap.submapper(path_prefix=ADMIN_PREFIX,
366 controller='admin/defaults') as m:
366 controller='admin/defaults') as m:
367 m.connect('admin_defaults_repositories', '/defaults/repositories',
367 m.connect('admin_defaults_repositories', '/defaults/repositories',
368 action='update_repository_defaults', conditions={'method': ['POST']})
368 action='update_repository_defaults', conditions={'method': ['POST']})
369 m.connect('admin_defaults_repositories', '/defaults/repositories',
369 m.connect('admin_defaults_repositories', '/defaults/repositories',
370 action='index', conditions={'method': ['GET']})
370 action='index', conditions={'method': ['GET']})
371
371
372 # ADMIN DEBUG STYLE ROUTES
372 # ADMIN DEBUG STYLE ROUTES
373 if str2bool(config.get('debug_style')):
373 if str2bool(config.get('debug_style')):
374 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
374 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
375 controller='debug_style') as m:
375 controller='debug_style') as m:
376 m.connect('debug_style_home', '',
376 m.connect('debug_style_home', '',
377 action='index', conditions={'method': ['GET']})
377 action='index', conditions={'method': ['GET']})
378 m.connect('debug_style_template', '/t/{t_path}',
378 m.connect('debug_style_template', '/t/{t_path}',
379 action='template', conditions={'method': ['GET']})
379 action='template', conditions={'method': ['GET']})
380
380
381 # ADMIN SETTINGS ROUTES
381 # ADMIN SETTINGS ROUTES
382 with rmap.submapper(path_prefix=ADMIN_PREFIX,
382 with rmap.submapper(path_prefix=ADMIN_PREFIX,
383 controller='admin/settings') as m:
383 controller='admin/settings') as m:
384
384
385 # default
385 # default
386 m.connect('admin_settings', '/settings',
386 m.connect('admin_settings', '/settings',
387 action='settings_global_update',
387 action='settings_global_update',
388 conditions={'method': ['POST']})
388 conditions={'method': ['POST']})
389 m.connect('admin_settings', '/settings',
389 m.connect('admin_settings', '/settings',
390 action='settings_global', conditions={'method': ['GET']})
390 action='settings_global', conditions={'method': ['GET']})
391
391
392 m.connect('admin_settings_vcs', '/settings/vcs',
392 m.connect('admin_settings_vcs', '/settings/vcs',
393 action='settings_vcs_update',
393 action='settings_vcs_update',
394 conditions={'method': ['POST']})
394 conditions={'method': ['POST']})
395 m.connect('admin_settings_vcs', '/settings/vcs',
395 m.connect('admin_settings_vcs', '/settings/vcs',
396 action='settings_vcs',
396 action='settings_vcs',
397 conditions={'method': ['GET']})
397 conditions={'method': ['GET']})
398 m.connect('admin_settings_vcs', '/settings/vcs',
398 m.connect('admin_settings_vcs', '/settings/vcs',
399 action='delete_svn_pattern',
399 action='delete_svn_pattern',
400 conditions={'method': ['DELETE']})
400 conditions={'method': ['DELETE']})
401
401
402 m.connect('admin_settings_mapping', '/settings/mapping',
402 m.connect('admin_settings_mapping', '/settings/mapping',
403 action='settings_mapping_update',
403 action='settings_mapping_update',
404 conditions={'method': ['POST']})
404 conditions={'method': ['POST']})
405 m.connect('admin_settings_mapping', '/settings/mapping',
405 m.connect('admin_settings_mapping', '/settings/mapping',
406 action='settings_mapping', conditions={'method': ['GET']})
406 action='settings_mapping', conditions={'method': ['GET']})
407
407
408 m.connect('admin_settings_global', '/settings/global',
408 m.connect('admin_settings_global', '/settings/global',
409 action='settings_global_update',
409 action='settings_global_update',
410 conditions={'method': ['POST']})
410 conditions={'method': ['POST']})
411 m.connect('admin_settings_global', '/settings/global',
411 m.connect('admin_settings_global', '/settings/global',
412 action='settings_global', conditions={'method': ['GET']})
412 action='settings_global', conditions={'method': ['GET']})
413
413
414 m.connect('admin_settings_visual', '/settings/visual',
414 m.connect('admin_settings_visual', '/settings/visual',
415 action='settings_visual_update',
415 action='settings_visual_update',
416 conditions={'method': ['POST']})
416 conditions={'method': ['POST']})
417 m.connect('admin_settings_visual', '/settings/visual',
417 m.connect('admin_settings_visual', '/settings/visual',
418 action='settings_visual', conditions={'method': ['GET']})
418 action='settings_visual', conditions={'method': ['GET']})
419
419
420 m.connect('admin_settings_issuetracker',
420 m.connect('admin_settings_issuetracker',
421 '/settings/issue-tracker', action='settings_issuetracker',
421 '/settings/issue-tracker', action='settings_issuetracker',
422 conditions={'method': ['GET']})
422 conditions={'method': ['GET']})
423 m.connect('admin_settings_issuetracker_save',
423 m.connect('admin_settings_issuetracker_save',
424 '/settings/issue-tracker/save',
424 '/settings/issue-tracker/save',
425 action='settings_issuetracker_save',
425 action='settings_issuetracker_save',
426 conditions={'method': ['POST']})
426 conditions={'method': ['POST']})
427 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
427 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
428 action='settings_issuetracker_test',
428 action='settings_issuetracker_test',
429 conditions={'method': ['POST']})
429 conditions={'method': ['POST']})
430 m.connect('admin_issuetracker_delete',
430 m.connect('admin_issuetracker_delete',
431 '/settings/issue-tracker/delete',
431 '/settings/issue-tracker/delete',
432 action='settings_issuetracker_delete',
432 action='settings_issuetracker_delete',
433 conditions={'method': ['DELETE']})
433 conditions={'method': ['DELETE']})
434
434
435 m.connect('admin_settings_email', '/settings/email',
435 m.connect('admin_settings_email', '/settings/email',
436 action='settings_email_update',
436 action='settings_email_update',
437 conditions={'method': ['POST']})
437 conditions={'method': ['POST']})
438 m.connect('admin_settings_email', '/settings/email',
438 m.connect('admin_settings_email', '/settings/email',
439 action='settings_email', conditions={'method': ['GET']})
439 action='settings_email', conditions={'method': ['GET']})
440
440
441 m.connect('admin_settings_hooks', '/settings/hooks',
441 m.connect('admin_settings_hooks', '/settings/hooks',
442 action='settings_hooks_update',
442 action='settings_hooks_update',
443 conditions={'method': ['POST', 'DELETE']})
443 conditions={'method': ['POST', 'DELETE']})
444 m.connect('admin_settings_hooks', '/settings/hooks',
444 m.connect('admin_settings_hooks', '/settings/hooks',
445 action='settings_hooks', conditions={'method': ['GET']})
445 action='settings_hooks', conditions={'method': ['GET']})
446
446
447 m.connect('admin_settings_search', '/settings/search',
447 m.connect('admin_settings_search', '/settings/search',
448 action='settings_search', conditions={'method': ['GET']})
448 action='settings_search', conditions={'method': ['GET']})
449
449
450 m.connect('admin_settings_supervisor', '/settings/supervisor',
450 m.connect('admin_settings_supervisor', '/settings/supervisor',
451 action='settings_supervisor', conditions={'method': ['GET']})
451 action='settings_supervisor', conditions={'method': ['GET']})
452 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
452 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
453 action='settings_supervisor_log', conditions={'method': ['GET']})
453 action='settings_supervisor_log', conditions={'method': ['GET']})
454
454
455 m.connect('admin_settings_labs', '/settings/labs',
455 m.connect('admin_settings_labs', '/settings/labs',
456 action='settings_labs_update',
456 action='settings_labs_update',
457 conditions={'method': ['POST']})
457 conditions={'method': ['POST']})
458 m.connect('admin_settings_labs', '/settings/labs',
458 m.connect('admin_settings_labs', '/settings/labs',
459 action='settings_labs', conditions={'method': ['GET']})
459 action='settings_labs', conditions={'method': ['GET']})
460
460
461 # ADMIN MY ACCOUNT
461 # ADMIN MY ACCOUNT
462 with rmap.submapper(path_prefix=ADMIN_PREFIX,
462 with rmap.submapper(path_prefix=ADMIN_PREFIX,
463 controller='admin/my_account') as m:
463 controller='admin/my_account') as m:
464
464
465 m.connect('my_account_edit', '/my_account/edit',
466 action='my_account_edit', conditions={'method': ['GET']})
467 m.connect('my_account', '/my_account/update',
468 action='my_account_update', conditions={'method': ['POST']})
469
470 # NOTE(marcink): this needs to be kept for password force flag to be
465 # NOTE(marcink): this needs to be kept for password force flag to be
471 # handler, remove after migration to pyramid
466 # handled in pylons controllers, remove after full migration to pyramid
472 m.connect('my_account_password', '/my_account/password',
467 m.connect('my_account_password', '/my_account/password',
473 action='my_account_password', conditions={'method': ['GET']})
468 action='my_account_password', conditions={'method': ['GET']})
474
469
475 m.connect('my_account_pullrequests', '/my_account/pull_requests',
476 action='my_account_pullrequests', conditions={'method': ['GET']})
477
478 # NOTIFICATION REST ROUTES
470 # NOTIFICATION REST ROUTES
479 with rmap.submapper(path_prefix=ADMIN_PREFIX,
471 with rmap.submapper(path_prefix=ADMIN_PREFIX,
480 controller='admin/notifications') as m:
472 controller='admin/notifications') as m:
481 m.connect('notifications', '/notifications',
473 m.connect('notifications', '/notifications',
482 action='index', conditions={'method': ['GET']})
474 action='index', conditions={'method': ['GET']})
483 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
475 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
484 action='mark_all_read', conditions={'method': ['POST']})
476 action='mark_all_read', conditions={'method': ['POST']})
485 m.connect('/notifications/{notification_id}',
477 m.connect('/notifications/{notification_id}',
486 action='update', conditions={'method': ['PUT']})
478 action='update', conditions={'method': ['PUT']})
487 m.connect('/notifications/{notification_id}',
479 m.connect('/notifications/{notification_id}',
488 action='delete', conditions={'method': ['DELETE']})
480 action='delete', conditions={'method': ['DELETE']})
489 m.connect('notification', '/notifications/{notification_id}',
481 m.connect('notification', '/notifications/{notification_id}',
490 action='show', conditions={'method': ['GET']})
482 action='show', conditions={'method': ['GET']})
491
483
492 # USER JOURNAL
484 # USER JOURNAL
493 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
485 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
494 controller='journal', action='index')
486 controller='journal', action='index')
495 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
487 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
496 controller='journal', action='journal_rss')
488 controller='journal', action='journal_rss')
497 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
489 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
498 controller='journal', action='journal_atom')
490 controller='journal', action='journal_atom')
499
491
500 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
492 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
501 controller='journal', action='public_journal')
493 controller='journal', action='public_journal')
502
494
503 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
495 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
504 controller='journal', action='public_journal_rss')
496 controller='journal', action='public_journal_rss')
505
497
506 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
498 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
507 controller='journal', action='public_journal_rss')
499 controller='journal', action='public_journal_rss')
508
500
509 rmap.connect('public_journal_atom',
501 rmap.connect('public_journal_atom',
510 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
502 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
511 action='public_journal_atom')
503 action='public_journal_atom')
512
504
513 rmap.connect('public_journal_atom_old',
505 rmap.connect('public_journal_atom_old',
514 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
506 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
515 action='public_journal_atom')
507 action='public_journal_atom')
516
508
517 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
509 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
518 controller='journal', action='toggle_following', jsroute=True,
510 controller='journal', action='toggle_following', jsroute=True,
519 conditions={'method': ['POST']})
511 conditions={'method': ['POST']})
520
512
521 # FEEDS
513 # FEEDS
522 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
514 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
523 controller='feed', action='rss',
515 controller='feed', action='rss',
524 conditions={'function': check_repo},
516 conditions={'function': check_repo},
525 requirements=URL_NAME_REQUIREMENTS)
517 requirements=URL_NAME_REQUIREMENTS)
526
518
527 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
519 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
528 controller='feed', action='atom',
520 controller='feed', action='atom',
529 conditions={'function': check_repo},
521 conditions={'function': check_repo},
530 requirements=URL_NAME_REQUIREMENTS)
522 requirements=URL_NAME_REQUIREMENTS)
531
523
532 #==========================================================================
524 #==========================================================================
533 # REPOSITORY ROUTES
525 # REPOSITORY ROUTES
534 #==========================================================================
526 #==========================================================================
535
527
536 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
528 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
537 controller='admin/repos', action='repo_creating',
529 controller='admin/repos', action='repo_creating',
538 requirements=URL_NAME_REQUIREMENTS)
530 requirements=URL_NAME_REQUIREMENTS)
539 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
531 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
540 controller='admin/repos', action='repo_check',
532 controller='admin/repos', action='repo_check',
541 requirements=URL_NAME_REQUIREMENTS)
533 requirements=URL_NAME_REQUIREMENTS)
542
534
543 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
535 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
544 controller='changeset', revision='tip',
536 controller='changeset', revision='tip',
545 conditions={'function': check_repo},
537 conditions={'function': check_repo},
546 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
538 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
547 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
539 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
548 controller='changeset', revision='tip', action='changeset_children',
540 controller='changeset', revision='tip', action='changeset_children',
549 conditions={'function': check_repo},
541 conditions={'function': check_repo},
550 requirements=URL_NAME_REQUIREMENTS)
542 requirements=URL_NAME_REQUIREMENTS)
551 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
543 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
552 controller='changeset', revision='tip', action='changeset_parents',
544 controller='changeset', revision='tip', action='changeset_parents',
553 conditions={'function': check_repo},
545 conditions={'function': check_repo},
554 requirements=URL_NAME_REQUIREMENTS)
546 requirements=URL_NAME_REQUIREMENTS)
555
547
556 # repo edit options
548 # repo edit options
557 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
549 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
558 controller='admin/repos', action='edit_fields',
550 controller='admin/repos', action='edit_fields',
559 conditions={'method': ['GET'], 'function': check_repo},
551 conditions={'method': ['GET'], 'function': check_repo},
560 requirements=URL_NAME_REQUIREMENTS)
552 requirements=URL_NAME_REQUIREMENTS)
561 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
553 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
562 controller='admin/repos', action='create_repo_field',
554 controller='admin/repos', action='create_repo_field',
563 conditions={'method': ['PUT'], 'function': check_repo},
555 conditions={'method': ['PUT'], 'function': check_repo},
564 requirements=URL_NAME_REQUIREMENTS)
556 requirements=URL_NAME_REQUIREMENTS)
565 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
557 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
566 controller='admin/repos', action='delete_repo_field',
558 controller='admin/repos', action='delete_repo_field',
567 conditions={'method': ['DELETE'], 'function': check_repo},
559 conditions={'method': ['DELETE'], 'function': check_repo},
568 requirements=URL_NAME_REQUIREMENTS)
560 requirements=URL_NAME_REQUIREMENTS)
569
561
570 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
562 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
571 controller='admin/repos', action='toggle_locking',
563 controller='admin/repos', action='toggle_locking',
572 conditions={'method': ['GET'], 'function': check_repo},
564 conditions={'method': ['GET'], 'function': check_repo},
573 requirements=URL_NAME_REQUIREMENTS)
565 requirements=URL_NAME_REQUIREMENTS)
574
566
575 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
567 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
576 controller='admin/repos', action='edit_remote_form',
568 controller='admin/repos', action='edit_remote_form',
577 conditions={'method': ['GET'], 'function': check_repo},
569 conditions={'method': ['GET'], 'function': check_repo},
578 requirements=URL_NAME_REQUIREMENTS)
570 requirements=URL_NAME_REQUIREMENTS)
579 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
571 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
580 controller='admin/repos', action='edit_remote',
572 controller='admin/repos', action='edit_remote',
581 conditions={'method': ['PUT'], 'function': check_repo},
573 conditions={'method': ['PUT'], 'function': check_repo},
582 requirements=URL_NAME_REQUIREMENTS)
574 requirements=URL_NAME_REQUIREMENTS)
583
575
584 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
576 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
585 controller='admin/repos', action='edit_statistics_form',
577 controller='admin/repos', action='edit_statistics_form',
586 conditions={'method': ['GET'], 'function': check_repo},
578 conditions={'method': ['GET'], 'function': check_repo},
587 requirements=URL_NAME_REQUIREMENTS)
579 requirements=URL_NAME_REQUIREMENTS)
588 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
580 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
589 controller='admin/repos', action='edit_statistics',
581 controller='admin/repos', action='edit_statistics',
590 conditions={'method': ['PUT'], 'function': check_repo},
582 conditions={'method': ['PUT'], 'function': check_repo},
591 requirements=URL_NAME_REQUIREMENTS)
583 requirements=URL_NAME_REQUIREMENTS)
592 rmap.connect('repo_settings_issuetracker',
584 rmap.connect('repo_settings_issuetracker',
593 '/{repo_name}/settings/issue-tracker',
585 '/{repo_name}/settings/issue-tracker',
594 controller='admin/repos', action='repo_issuetracker',
586 controller='admin/repos', action='repo_issuetracker',
595 conditions={'method': ['GET'], 'function': check_repo},
587 conditions={'method': ['GET'], 'function': check_repo},
596 requirements=URL_NAME_REQUIREMENTS)
588 requirements=URL_NAME_REQUIREMENTS)
597 rmap.connect('repo_issuetracker_test',
589 rmap.connect('repo_issuetracker_test',
598 '/{repo_name}/settings/issue-tracker/test',
590 '/{repo_name}/settings/issue-tracker/test',
599 controller='admin/repos', action='repo_issuetracker_test',
591 controller='admin/repos', action='repo_issuetracker_test',
600 conditions={'method': ['POST'], 'function': check_repo},
592 conditions={'method': ['POST'], 'function': check_repo},
601 requirements=URL_NAME_REQUIREMENTS)
593 requirements=URL_NAME_REQUIREMENTS)
602 rmap.connect('repo_issuetracker_delete',
594 rmap.connect('repo_issuetracker_delete',
603 '/{repo_name}/settings/issue-tracker/delete',
595 '/{repo_name}/settings/issue-tracker/delete',
604 controller='admin/repos', action='repo_issuetracker_delete',
596 controller='admin/repos', action='repo_issuetracker_delete',
605 conditions={'method': ['DELETE'], 'function': check_repo},
597 conditions={'method': ['DELETE'], 'function': check_repo},
606 requirements=URL_NAME_REQUIREMENTS)
598 requirements=URL_NAME_REQUIREMENTS)
607 rmap.connect('repo_issuetracker_save',
599 rmap.connect('repo_issuetracker_save',
608 '/{repo_name}/settings/issue-tracker/save',
600 '/{repo_name}/settings/issue-tracker/save',
609 controller='admin/repos', action='repo_issuetracker_save',
601 controller='admin/repos', action='repo_issuetracker_save',
610 conditions={'method': ['POST'], 'function': check_repo},
602 conditions={'method': ['POST'], 'function': check_repo},
611 requirements=URL_NAME_REQUIREMENTS)
603 requirements=URL_NAME_REQUIREMENTS)
612 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
604 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
613 controller='admin/repos', action='repo_settings_vcs_update',
605 controller='admin/repos', action='repo_settings_vcs_update',
614 conditions={'method': ['POST'], 'function': check_repo},
606 conditions={'method': ['POST'], 'function': check_repo},
615 requirements=URL_NAME_REQUIREMENTS)
607 requirements=URL_NAME_REQUIREMENTS)
616 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
608 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
617 controller='admin/repos', action='repo_settings_vcs',
609 controller='admin/repos', action='repo_settings_vcs',
618 conditions={'method': ['GET'], 'function': check_repo},
610 conditions={'method': ['GET'], 'function': check_repo},
619 requirements=URL_NAME_REQUIREMENTS)
611 requirements=URL_NAME_REQUIREMENTS)
620 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
612 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
621 controller='admin/repos', action='repo_delete_svn_pattern',
613 controller='admin/repos', action='repo_delete_svn_pattern',
622 conditions={'method': ['DELETE'], 'function': check_repo},
614 conditions={'method': ['DELETE'], 'function': check_repo},
623 requirements=URL_NAME_REQUIREMENTS)
615 requirements=URL_NAME_REQUIREMENTS)
624 rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest',
616 rmap.connect('repo_pullrequest_settings', '/{repo_name}/settings/pullrequest',
625 controller='admin/repos', action='repo_settings_pullrequest',
617 controller='admin/repos', action='repo_settings_pullrequest',
626 conditions={'method': ['GET', 'POST'], 'function': check_repo},
618 conditions={'method': ['GET', 'POST'], 'function': check_repo},
627 requirements=URL_NAME_REQUIREMENTS)
619 requirements=URL_NAME_REQUIREMENTS)
628
620
629 # still working url for backward compat.
621 # still working url for backward compat.
630 rmap.connect('raw_changeset_home_depraced',
622 rmap.connect('raw_changeset_home_depraced',
631 '/{repo_name}/raw-changeset/{revision}',
623 '/{repo_name}/raw-changeset/{revision}',
632 controller='changeset', action='changeset_raw',
624 controller='changeset', action='changeset_raw',
633 revision='tip', conditions={'function': check_repo},
625 revision='tip', conditions={'function': check_repo},
634 requirements=URL_NAME_REQUIREMENTS)
626 requirements=URL_NAME_REQUIREMENTS)
635
627
636 # new URLs
628 # new URLs
637 rmap.connect('changeset_raw_home',
629 rmap.connect('changeset_raw_home',
638 '/{repo_name}/changeset-diff/{revision}',
630 '/{repo_name}/changeset-diff/{revision}',
639 controller='changeset', action='changeset_raw',
631 controller='changeset', action='changeset_raw',
640 revision='tip', conditions={'function': check_repo},
632 revision='tip', conditions={'function': check_repo},
641 requirements=URL_NAME_REQUIREMENTS)
633 requirements=URL_NAME_REQUIREMENTS)
642
634
643 rmap.connect('changeset_patch_home',
635 rmap.connect('changeset_patch_home',
644 '/{repo_name}/changeset-patch/{revision}',
636 '/{repo_name}/changeset-patch/{revision}',
645 controller='changeset', action='changeset_patch',
637 controller='changeset', action='changeset_patch',
646 revision='tip', conditions={'function': check_repo},
638 revision='tip', conditions={'function': check_repo},
647 requirements=URL_NAME_REQUIREMENTS)
639 requirements=URL_NAME_REQUIREMENTS)
648
640
649 rmap.connect('changeset_download_home',
641 rmap.connect('changeset_download_home',
650 '/{repo_name}/changeset-download/{revision}',
642 '/{repo_name}/changeset-download/{revision}',
651 controller='changeset', action='changeset_download',
643 controller='changeset', action='changeset_download',
652 revision='tip', conditions={'function': check_repo},
644 revision='tip', conditions={'function': check_repo},
653 requirements=URL_NAME_REQUIREMENTS)
645 requirements=URL_NAME_REQUIREMENTS)
654
646
655 rmap.connect('changeset_comment',
647 rmap.connect('changeset_comment',
656 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
648 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
657 controller='changeset', revision='tip', action='comment',
649 controller='changeset', revision='tip', action='comment',
658 conditions={'function': check_repo},
650 conditions={'function': check_repo},
659 requirements=URL_NAME_REQUIREMENTS)
651 requirements=URL_NAME_REQUIREMENTS)
660
652
661 rmap.connect('changeset_comment_preview',
653 rmap.connect('changeset_comment_preview',
662 '/{repo_name}/changeset/comment/preview', jsroute=True,
654 '/{repo_name}/changeset/comment/preview', jsroute=True,
663 controller='changeset', action='preview_comment',
655 controller='changeset', action='preview_comment',
664 conditions={'function': check_repo, 'method': ['POST']},
656 conditions={'function': check_repo, 'method': ['POST']},
665 requirements=URL_NAME_REQUIREMENTS)
657 requirements=URL_NAME_REQUIREMENTS)
666
658
667 rmap.connect('changeset_comment_delete',
659 rmap.connect('changeset_comment_delete',
668 '/{repo_name}/changeset/comment/{comment_id}/delete',
660 '/{repo_name}/changeset/comment/{comment_id}/delete',
669 controller='changeset', action='delete_comment',
661 controller='changeset', action='delete_comment',
670 conditions={'function': check_repo, 'method': ['DELETE']},
662 conditions={'function': check_repo, 'method': ['DELETE']},
671 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
663 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
672
664
673 rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
665 rmap.connect('changeset_info', '/{repo_name}/changeset_info/{revision}',
674 controller='changeset', action='changeset_info',
666 controller='changeset', action='changeset_info',
675 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
667 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
676
668
677 rmap.connect('compare_home',
669 rmap.connect('compare_home',
678 '/{repo_name}/compare',
670 '/{repo_name}/compare',
679 controller='compare', action='index',
671 controller='compare', action='index',
680 conditions={'function': check_repo},
672 conditions={'function': check_repo},
681 requirements=URL_NAME_REQUIREMENTS)
673 requirements=URL_NAME_REQUIREMENTS)
682
674
683 rmap.connect('compare_url',
675 rmap.connect('compare_url',
684 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
676 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
685 controller='compare', action='compare',
677 controller='compare', action='compare',
686 conditions={'function': check_repo},
678 conditions={'function': check_repo},
687 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
679 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
688
680
689 rmap.connect('pullrequest_home',
681 rmap.connect('pullrequest_home',
690 '/{repo_name}/pull-request/new', controller='pullrequests',
682 '/{repo_name}/pull-request/new', controller='pullrequests',
691 action='index', conditions={'function': check_repo,
683 action='index', conditions={'function': check_repo,
692 'method': ['GET']},
684 'method': ['GET']},
693 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
685 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
694
686
695 rmap.connect('pullrequest',
687 rmap.connect('pullrequest',
696 '/{repo_name}/pull-request/new', controller='pullrequests',
688 '/{repo_name}/pull-request/new', controller='pullrequests',
697 action='create', conditions={'function': check_repo,
689 action='create', conditions={'function': check_repo,
698 'method': ['POST']},
690 'method': ['POST']},
699 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
691 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
700
692
701 rmap.connect('pullrequest_repo_refs',
693 rmap.connect('pullrequest_repo_refs',
702 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
694 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
703 controller='pullrequests',
695 controller='pullrequests',
704 action='get_repo_refs',
696 action='get_repo_refs',
705 conditions={'function': check_repo, 'method': ['GET']},
697 conditions={'function': check_repo, 'method': ['GET']},
706 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
698 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
707
699
708 rmap.connect('pullrequest_repo_destinations',
700 rmap.connect('pullrequest_repo_destinations',
709 '/{repo_name}/pull-request/repo-destinations',
701 '/{repo_name}/pull-request/repo-destinations',
710 controller='pullrequests',
702 controller='pullrequests',
711 action='get_repo_destinations',
703 action='get_repo_destinations',
712 conditions={'function': check_repo, 'method': ['GET']},
704 conditions={'function': check_repo, 'method': ['GET']},
713 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
705 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
714
706
715 rmap.connect('pullrequest_show',
707 rmap.connect('pullrequest_show',
716 '/{repo_name}/pull-request/{pull_request_id}',
708 '/{repo_name}/pull-request/{pull_request_id}',
717 controller='pullrequests',
709 controller='pullrequests',
718 action='show', conditions={'function': check_repo,
710 action='show', conditions={'function': check_repo,
719 'method': ['GET']},
711 'method': ['GET']},
720 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
712 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
721
713
722 rmap.connect('pullrequest_update',
714 rmap.connect('pullrequest_update',
723 '/{repo_name}/pull-request/{pull_request_id}',
715 '/{repo_name}/pull-request/{pull_request_id}',
724 controller='pullrequests',
716 controller='pullrequests',
725 action='update', conditions={'function': check_repo,
717 action='update', conditions={'function': check_repo,
726 'method': ['PUT']},
718 'method': ['PUT']},
727 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
719 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
728
720
729 rmap.connect('pullrequest_merge',
721 rmap.connect('pullrequest_merge',
730 '/{repo_name}/pull-request/{pull_request_id}',
722 '/{repo_name}/pull-request/{pull_request_id}',
731 controller='pullrequests',
723 controller='pullrequests',
732 action='merge', conditions={'function': check_repo,
724 action='merge', conditions={'function': check_repo,
733 'method': ['POST']},
725 'method': ['POST']},
734 requirements=URL_NAME_REQUIREMENTS)
726 requirements=URL_NAME_REQUIREMENTS)
735
727
736 rmap.connect('pullrequest_delete',
728 rmap.connect('pullrequest_delete',
737 '/{repo_name}/pull-request/{pull_request_id}',
729 '/{repo_name}/pull-request/{pull_request_id}',
738 controller='pullrequests',
730 controller='pullrequests',
739 action='delete', conditions={'function': check_repo,
731 action='delete', conditions={'function': check_repo,
740 'method': ['DELETE']},
732 'method': ['DELETE']},
741 requirements=URL_NAME_REQUIREMENTS)
733 requirements=URL_NAME_REQUIREMENTS)
742
734
743 rmap.connect('pullrequest_comment',
735 rmap.connect('pullrequest_comment',
744 '/{repo_name}/pull-request-comment/{pull_request_id}',
736 '/{repo_name}/pull-request-comment/{pull_request_id}',
745 controller='pullrequests',
737 controller='pullrequests',
746 action='comment', conditions={'function': check_repo,
738 action='comment', conditions={'function': check_repo,
747 'method': ['POST']},
739 'method': ['POST']},
748 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
740 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
749
741
750 rmap.connect('pullrequest_comment_delete',
742 rmap.connect('pullrequest_comment_delete',
751 '/{repo_name}/pull-request-comment/{comment_id}/delete',
743 '/{repo_name}/pull-request-comment/{comment_id}/delete',
752 controller='pullrequests', action='delete_comment',
744 controller='pullrequests', action='delete_comment',
753 conditions={'function': check_repo, 'method': ['DELETE']},
745 conditions={'function': check_repo, 'method': ['DELETE']},
754 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
746 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
755
747
756 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
748 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
757 controller='changelog', conditions={'function': check_repo},
749 controller='changelog', conditions={'function': check_repo},
758 requirements=URL_NAME_REQUIREMENTS)
750 requirements=URL_NAME_REQUIREMENTS)
759
751
760 rmap.connect('changelog_file_home',
752 rmap.connect('changelog_file_home',
761 '/{repo_name}/changelog/{revision}/{f_path}',
753 '/{repo_name}/changelog/{revision}/{f_path}',
762 controller='changelog', f_path=None,
754 controller='changelog', f_path=None,
763 conditions={'function': check_repo},
755 conditions={'function': check_repo},
764 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
756 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
765
757
766 rmap.connect('changelog_elements', '/{repo_name}/changelog_details',
758 rmap.connect('changelog_elements', '/{repo_name}/changelog_details',
767 controller='changelog', action='changelog_elements',
759 controller='changelog', action='changelog_elements',
768 conditions={'function': check_repo},
760 conditions={'function': check_repo},
769 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
761 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
770
762
771 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
763 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
772 controller='files', revision='tip', f_path='',
764 controller='files', revision='tip', f_path='',
773 conditions={'function': check_repo},
765 conditions={'function': check_repo},
774 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
766 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
775
767
776 rmap.connect('files_home_simple_catchrev',
768 rmap.connect('files_home_simple_catchrev',
777 '/{repo_name}/files/{revision}',
769 '/{repo_name}/files/{revision}',
778 controller='files', revision='tip', f_path='',
770 controller='files', revision='tip', f_path='',
779 conditions={'function': check_repo},
771 conditions={'function': check_repo},
780 requirements=URL_NAME_REQUIREMENTS)
772 requirements=URL_NAME_REQUIREMENTS)
781
773
782 rmap.connect('files_home_simple_catchall',
774 rmap.connect('files_home_simple_catchall',
783 '/{repo_name}/files',
775 '/{repo_name}/files',
784 controller='files', revision='tip', f_path='',
776 controller='files', revision='tip', f_path='',
785 conditions={'function': check_repo},
777 conditions={'function': check_repo},
786 requirements=URL_NAME_REQUIREMENTS)
778 requirements=URL_NAME_REQUIREMENTS)
787
779
788 rmap.connect('files_history_home',
780 rmap.connect('files_history_home',
789 '/{repo_name}/history/{revision}/{f_path}',
781 '/{repo_name}/history/{revision}/{f_path}',
790 controller='files', action='history', revision='tip', f_path='',
782 controller='files', action='history', revision='tip', f_path='',
791 conditions={'function': check_repo},
783 conditions={'function': check_repo},
792 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
784 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
793
785
794 rmap.connect('files_authors_home',
786 rmap.connect('files_authors_home',
795 '/{repo_name}/authors/{revision}/{f_path}',
787 '/{repo_name}/authors/{revision}/{f_path}',
796 controller='files', action='authors', revision='tip', f_path='',
788 controller='files', action='authors', revision='tip', f_path='',
797 conditions={'function': check_repo},
789 conditions={'function': check_repo},
798 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
790 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
799
791
800 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
792 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
801 controller='files', action='diff', f_path='',
793 controller='files', action='diff', f_path='',
802 conditions={'function': check_repo},
794 conditions={'function': check_repo},
803 requirements=URL_NAME_REQUIREMENTS)
795 requirements=URL_NAME_REQUIREMENTS)
804
796
805 rmap.connect('files_diff_2way_home',
797 rmap.connect('files_diff_2way_home',
806 '/{repo_name}/diff-2way/{f_path}',
798 '/{repo_name}/diff-2way/{f_path}',
807 controller='files', action='diff_2way', f_path='',
799 controller='files', action='diff_2way', f_path='',
808 conditions={'function': check_repo},
800 conditions={'function': check_repo},
809 requirements=URL_NAME_REQUIREMENTS)
801 requirements=URL_NAME_REQUIREMENTS)
810
802
811 rmap.connect('files_rawfile_home',
803 rmap.connect('files_rawfile_home',
812 '/{repo_name}/rawfile/{revision}/{f_path}',
804 '/{repo_name}/rawfile/{revision}/{f_path}',
813 controller='files', action='rawfile', revision='tip',
805 controller='files', action='rawfile', revision='tip',
814 f_path='', conditions={'function': check_repo},
806 f_path='', conditions={'function': check_repo},
815 requirements=URL_NAME_REQUIREMENTS)
807 requirements=URL_NAME_REQUIREMENTS)
816
808
817 rmap.connect('files_raw_home',
809 rmap.connect('files_raw_home',
818 '/{repo_name}/raw/{revision}/{f_path}',
810 '/{repo_name}/raw/{revision}/{f_path}',
819 controller='files', action='raw', revision='tip', f_path='',
811 controller='files', action='raw', revision='tip', f_path='',
820 conditions={'function': check_repo},
812 conditions={'function': check_repo},
821 requirements=URL_NAME_REQUIREMENTS)
813 requirements=URL_NAME_REQUIREMENTS)
822
814
823 rmap.connect('files_render_home',
815 rmap.connect('files_render_home',
824 '/{repo_name}/render/{revision}/{f_path}',
816 '/{repo_name}/render/{revision}/{f_path}',
825 controller='files', action='index', revision='tip', f_path='',
817 controller='files', action='index', revision='tip', f_path='',
826 rendered=True, conditions={'function': check_repo},
818 rendered=True, conditions={'function': check_repo},
827 requirements=URL_NAME_REQUIREMENTS)
819 requirements=URL_NAME_REQUIREMENTS)
828
820
829 rmap.connect('files_annotate_home',
821 rmap.connect('files_annotate_home',
830 '/{repo_name}/annotate/{revision}/{f_path}',
822 '/{repo_name}/annotate/{revision}/{f_path}',
831 controller='files', action='index', revision='tip',
823 controller='files', action='index', revision='tip',
832 f_path='', annotate=True, conditions={'function': check_repo},
824 f_path='', annotate=True, conditions={'function': check_repo},
833 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
825 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
834
826
835 rmap.connect('files_annotate_previous',
827 rmap.connect('files_annotate_previous',
836 '/{repo_name}/annotate-previous/{revision}/{f_path}',
828 '/{repo_name}/annotate-previous/{revision}/{f_path}',
837 controller='files', action='annotate_previous', revision='tip',
829 controller='files', action='annotate_previous', revision='tip',
838 f_path='', annotate=True, conditions={'function': check_repo},
830 f_path='', annotate=True, conditions={'function': check_repo},
839 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
831 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
840
832
841 rmap.connect('files_edit',
833 rmap.connect('files_edit',
842 '/{repo_name}/edit/{revision}/{f_path}',
834 '/{repo_name}/edit/{revision}/{f_path}',
843 controller='files', action='edit', revision='tip',
835 controller='files', action='edit', revision='tip',
844 f_path='',
836 f_path='',
845 conditions={'function': check_repo, 'method': ['POST']},
837 conditions={'function': check_repo, 'method': ['POST']},
846 requirements=URL_NAME_REQUIREMENTS)
838 requirements=URL_NAME_REQUIREMENTS)
847
839
848 rmap.connect('files_edit_home',
840 rmap.connect('files_edit_home',
849 '/{repo_name}/edit/{revision}/{f_path}',
841 '/{repo_name}/edit/{revision}/{f_path}',
850 controller='files', action='edit_home', revision='tip',
842 controller='files', action='edit_home', revision='tip',
851 f_path='', conditions={'function': check_repo},
843 f_path='', conditions={'function': check_repo},
852 requirements=URL_NAME_REQUIREMENTS)
844 requirements=URL_NAME_REQUIREMENTS)
853
845
854 rmap.connect('files_add',
846 rmap.connect('files_add',
855 '/{repo_name}/add/{revision}/{f_path}',
847 '/{repo_name}/add/{revision}/{f_path}',
856 controller='files', action='add', revision='tip',
848 controller='files', action='add', revision='tip',
857 f_path='',
849 f_path='',
858 conditions={'function': check_repo, 'method': ['POST']},
850 conditions={'function': check_repo, 'method': ['POST']},
859 requirements=URL_NAME_REQUIREMENTS)
851 requirements=URL_NAME_REQUIREMENTS)
860
852
861 rmap.connect('files_add_home',
853 rmap.connect('files_add_home',
862 '/{repo_name}/add/{revision}/{f_path}',
854 '/{repo_name}/add/{revision}/{f_path}',
863 controller='files', action='add_home', revision='tip',
855 controller='files', action='add_home', revision='tip',
864 f_path='', conditions={'function': check_repo},
856 f_path='', conditions={'function': check_repo},
865 requirements=URL_NAME_REQUIREMENTS)
857 requirements=URL_NAME_REQUIREMENTS)
866
858
867 rmap.connect('files_delete',
859 rmap.connect('files_delete',
868 '/{repo_name}/delete/{revision}/{f_path}',
860 '/{repo_name}/delete/{revision}/{f_path}',
869 controller='files', action='delete', revision='tip',
861 controller='files', action='delete', revision='tip',
870 f_path='',
862 f_path='',
871 conditions={'function': check_repo, 'method': ['POST']},
863 conditions={'function': check_repo, 'method': ['POST']},
872 requirements=URL_NAME_REQUIREMENTS)
864 requirements=URL_NAME_REQUIREMENTS)
873
865
874 rmap.connect('files_delete_home',
866 rmap.connect('files_delete_home',
875 '/{repo_name}/delete/{revision}/{f_path}',
867 '/{repo_name}/delete/{revision}/{f_path}',
876 controller='files', action='delete_home', revision='tip',
868 controller='files', action='delete_home', revision='tip',
877 f_path='', conditions={'function': check_repo},
869 f_path='', conditions={'function': check_repo},
878 requirements=URL_NAME_REQUIREMENTS)
870 requirements=URL_NAME_REQUIREMENTS)
879
871
880 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
872 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
881 controller='files', action='archivefile',
873 controller='files', action='archivefile',
882 conditions={'function': check_repo},
874 conditions={'function': check_repo},
883 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
875 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
884
876
885 rmap.connect('files_nodelist_home',
877 rmap.connect('files_nodelist_home',
886 '/{repo_name}/nodelist/{revision}/{f_path}',
878 '/{repo_name}/nodelist/{revision}/{f_path}',
887 controller='files', action='nodelist',
879 controller='files', action='nodelist',
888 conditions={'function': check_repo},
880 conditions={'function': check_repo},
889 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
881 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
890
882
891 rmap.connect('files_nodetree_full',
883 rmap.connect('files_nodetree_full',
892 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
884 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
893 controller='files', action='nodetree_full',
885 controller='files', action='nodetree_full',
894 conditions={'function': check_repo},
886 conditions={'function': check_repo},
895 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
887 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
896
888
897 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
889 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
898 controller='forks', action='fork_create',
890 controller='forks', action='fork_create',
899 conditions={'function': check_repo, 'method': ['POST']},
891 conditions={'function': check_repo, 'method': ['POST']},
900 requirements=URL_NAME_REQUIREMENTS)
892 requirements=URL_NAME_REQUIREMENTS)
901
893
902 rmap.connect('repo_fork_home', '/{repo_name}/fork',
894 rmap.connect('repo_fork_home', '/{repo_name}/fork',
903 controller='forks', action='fork',
895 controller='forks', action='fork',
904 conditions={'function': check_repo},
896 conditions={'function': check_repo},
905 requirements=URL_NAME_REQUIREMENTS)
897 requirements=URL_NAME_REQUIREMENTS)
906
898
907 rmap.connect('repo_forks_home', '/{repo_name}/forks',
899 rmap.connect('repo_forks_home', '/{repo_name}/forks',
908 controller='forks', action='forks',
900 controller='forks', action='forks',
909 conditions={'function': check_repo},
901 conditions={'function': check_repo},
910 requirements=URL_NAME_REQUIREMENTS)
902 requirements=URL_NAME_REQUIREMENTS)
911
903
912 return rmap
904 return rmap
@@ -1,165 +1,169 b''
1
1
2 /******************************************************************************
2 /******************************************************************************
3 * *
3 * *
4 * DO NOT CHANGE THIS FILE MANUALLY *
4 * DO NOT CHANGE THIS FILE MANUALLY *
5 * *
5 * *
6 * *
6 * *
7 * This file is automatically generated when the app starts up with *
7 * This file is automatically generated when the app starts up with *
8 * generate_js_files = true *
8 * generate_js_files = true *
9 * *
9 * *
10 * To add a route here pass jsroute=True to the route definition in the app *
10 * To add a route here pass jsroute=True to the route definition in the app *
11 * *
11 * *
12 ******************************************************************************/
12 ******************************************************************************/
13 function registerRCRoutes() {
13 function registerRCRoutes() {
14 // routes registration
14 // routes registration
15 pyroutes.register('new_repo', '/_admin/create_repository', []);
15 pyroutes.register('new_repo', '/_admin/create_repository', []);
16 pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
16 pyroutes.register('edit_user', '/_admin/users/%(user_id)s/edit', ['user_id']);
17 pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
17 pyroutes.register('edit_user_group_members', '/_admin/user_groups/%(user_group_id)s/edit/members', ['user_group_id']);
18 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
18 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
19 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
19 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
20 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
20 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
21 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
21 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
22 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
22 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
23 pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
23 pyroutes.register('changeset_info', '/%(repo_name)s/changeset_info/%(revision)s', ['repo_name', 'revision']);
24 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']);
24 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']);
25 pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
25 pyroutes.register('pullrequest_home', '/%(repo_name)s/pull-request/new', ['repo_name']);
26 pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
26 pyroutes.register('pullrequest', '/%(repo_name)s/pull-request/new', ['repo_name']);
27 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
27 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
28 pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
28 pyroutes.register('pullrequest_repo_destinations', '/%(repo_name)s/pull-request/repo-destinations', ['repo_name']);
29 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
29 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
30 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
30 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
31 pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
31 pyroutes.register('pullrequest_comment', '/%(repo_name)s/pull-request-comment/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
32 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
32 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request-comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
33 pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
33 pyroutes.register('changelog_home', '/%(repo_name)s/changelog', ['repo_name']);
34 pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
34 pyroutes.register('changelog_file_home', '/%(repo_name)s/changelog/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
35 pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']);
35 pyroutes.register('changelog_elements', '/%(repo_name)s/changelog_details', ['repo_name']);
36 pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
36 pyroutes.register('files_home', '/%(repo_name)s/files/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
37 pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
37 pyroutes.register('files_history_home', '/%(repo_name)s/history/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
38 pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
38 pyroutes.register('files_authors_home', '/%(repo_name)s/authors/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
39 pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
39 pyroutes.register('files_annotate_home', '/%(repo_name)s/annotate/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
40 pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
40 pyroutes.register('files_annotate_previous', '/%(repo_name)s/annotate-previous/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
41 pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
41 pyroutes.register('files_archive_home', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
42 pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
42 pyroutes.register('files_nodelist_home', '/%(repo_name)s/nodelist/%(revision)s/%(f_path)s', ['repo_name', 'revision', 'f_path']);
43 pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
43 pyroutes.register('files_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
44 pyroutes.register('favicon', '/favicon.ico', []);
44 pyroutes.register('favicon', '/favicon.ico', []);
45 pyroutes.register('robots', '/robots.txt', []);
45 pyroutes.register('robots', '/robots.txt', []);
46 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
46 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
47 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
47 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
48 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
48 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
49 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
49 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
50 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
50 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
51 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
51 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
52 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/settings/integrations', ['repo_group_name']);
52 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/settings/integrations', ['repo_group_name']);
53 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
53 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
54 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
54 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/settings/integrations/new', ['repo_group_name']);
55 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
55 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
56 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
56 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
57 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
57 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
58 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
58 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
59 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
59 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
60 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
60 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
61 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
61 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
62 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
62 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
63 pyroutes.register('admin_home', '/_admin', []);
63 pyroutes.register('admin_home', '/_admin', []);
64 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
64 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
65 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
65 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
66 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
66 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
67 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
67 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
68 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
68 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
69 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
69 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
70 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
70 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
71 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
71 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
72 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
72 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
73 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
73 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
74 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
74 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
75 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
75 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
76 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
76 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
77 pyroutes.register('users', '/_admin/users', []);
77 pyroutes.register('users', '/_admin/users', []);
78 pyroutes.register('users_data', '/_admin/users_data', []);
78 pyroutes.register('users_data', '/_admin/users_data', []);
79 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
79 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
80 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
80 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
81 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
81 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
82 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
82 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
83 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
83 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
84 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
84 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
85 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
85 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
86 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
86 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
87 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
87 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
88 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
88 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
89 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
89 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
90 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
90 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
91 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
91 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
92 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
92 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
93 pyroutes.register('channelstream_proxy', '/_channelstream', []);
93 pyroutes.register('channelstream_proxy', '/_channelstream', []);
94 pyroutes.register('login', '/_admin/login', []);
94 pyroutes.register('login', '/_admin/login', []);
95 pyroutes.register('logout', '/_admin/logout', []);
95 pyroutes.register('logout', '/_admin/logout', []);
96 pyroutes.register('register', '/_admin/register', []);
96 pyroutes.register('register', '/_admin/register', []);
97 pyroutes.register('reset_password', '/_admin/password_reset', []);
97 pyroutes.register('reset_password', '/_admin/password_reset', []);
98 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
98 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
99 pyroutes.register('home', '/', []);
99 pyroutes.register('home', '/', []);
100 pyroutes.register('user_autocomplete_data', '/_users', []);
100 pyroutes.register('user_autocomplete_data', '/_users', []);
101 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
101 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
102 pyroutes.register('repo_list_data', '/_repos', []);
102 pyroutes.register('repo_list_data', '/_repos', []);
103 pyroutes.register('goto_switcher_data', '/_goto_data', []);
103 pyroutes.register('goto_switcher_data', '/_goto_data', []);
104 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
104 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
105 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
105 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
106 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
106 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
107 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
107 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
108 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
108 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
109 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
109 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
110 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
110 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
111 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
111 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
112 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
112 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
113 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
113 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
114 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
114 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
115 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
115 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
116 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
116 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
117 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
117 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
118 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
118 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
119 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
119 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
120 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
120 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
121 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
121 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
122 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
122 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
123 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
123 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
124 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
124 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
125 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
125 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
126 pyroutes.register('repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
126 pyroutes.register('repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
127 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
127 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
128 pyroutes.register('strip', '/%(repo_name)s/settings/strip', ['repo_name']);
128 pyroutes.register('strip', '/%(repo_name)s/settings/strip', ['repo_name']);
129 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
129 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
130 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
130 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
131 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
131 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
132 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
132 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
133 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
133 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
134 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
134 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
135 pyroutes.register('search', '/_admin/search', []);
135 pyroutes.register('search', '/_admin/search', []);
136 pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']);
136 pyroutes.register('search_repo', '/%(repo_name)s/search', ['repo_name']);
137 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
137 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
138 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
138 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
139 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
140 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
139 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
141 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
140 pyroutes.register('my_account_password_update', '/_admin/my_account/password', []);
142 pyroutes.register('my_account_password_update', '/_admin/my_account/password', []);
141 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
143 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
142 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
144 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
143 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
145 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
144 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
146 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
145 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
147 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
146 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
148 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
147 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
149 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
148 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
150 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
149 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
151 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
150 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
152 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
151 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
153 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
154 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
155 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
152 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
156 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
153 pyroutes.register('gists_show', '/_admin/gists', []);
157 pyroutes.register('gists_show', '/_admin/gists', []);
154 pyroutes.register('gists_new', '/_admin/gists/new', []);
158 pyroutes.register('gists_new', '/_admin/gists/new', []);
155 pyroutes.register('gists_create', '/_admin/gists/create', []);
159 pyroutes.register('gists_create', '/_admin/gists/create', []);
156 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
160 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
157 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
161 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
158 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
162 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
159 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
163 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
160 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
164 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
161 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/%(revision)s', ['gist_id', 'revision']);
165 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/%(revision)s', ['gist_id', 'revision']);
162 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
166 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
163 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
167 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
164 pyroutes.register('apiv2', '/_admin/api', []);
168 pyroutes.register('apiv2', '/_admin/api', []);
165 }
169 }
@@ -1,52 +1,52 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.mako"/>
2 <%inherit file="/base/base.mako"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('My account')} ${c.rhodecode_user.username}
5 ${_('My account')} ${c.rhodecode_user.username}
6 %if c.rhodecode_name:
6 %if c.rhodecode_name:
7 &middot; ${h.branding(c.rhodecode_name)}
7 &middot; ${h.branding(c.rhodecode_name)}
8 %endif
8 %endif
9 </%def>
9 </%def>
10
10
11 <%def name="breadcrumbs_links()">
11 <%def name="breadcrumbs_links()">
12 ${_('My Account')}
12 ${_('My Account')}
13 </%def>
13 </%def>
14
14
15 <%def name="menu_bar_nav()">
15 <%def name="menu_bar_nav()">
16 ${self.menu_items(active='my_account')}
16 ${self.menu_items(active='my_account')}
17 </%def>
17 </%def>
18
18
19 <%def name="main()">
19 <%def name="main()">
20 <div class="box">
20 <div class="box">
21 <div class="title">
21 <div class="title">
22 ${self.breadcrumbs()}
22 ${self.breadcrumbs()}
23 </div>
23 </div>
24
24
25 <div class="sidebar-col-wrapper scw-small">
25 <div class="sidebar-col-wrapper scw-small">
26 ##main
26 ##main
27 <div class="sidebar">
27 <div class="sidebar">
28 <ul class="nav nav-pills nav-stacked">
28 <ul class="nav nav-pills nav-stacked">
29 <li class="${'active' if c.active=='profile' or c.active=='profile_edit' else ''}"><a href="${h.route_path('my_account_profile')}">${_('Profile')}</a></li>
29 <li class="${'active' if c.active=='profile' or c.active=='profile_edit' else ''}"><a href="${h.route_path('my_account_profile')}">${_('Profile')}</a></li>
30 <li class="${'active' if c.active=='password' else ''}"><a href="${h.route_path('my_account_password')}">${_('Password')}</a></li>
30 <li class="${'active' if c.active=='password' else ''}"><a href="${h.route_path('my_account_password')}">${_('Password')}</a></li>
31 <li class="${'active' if c.active=='auth_tokens' else ''}"><a href="${h.route_path('my_account_auth_tokens')}">${_('Auth Tokens')}</a></li>
31 <li class="${'active' if c.active=='auth_tokens' else ''}"><a href="${h.route_path('my_account_auth_tokens')}">${_('Auth Tokens')}</a></li>
32 ## TODO: Find a better integration of oauth views into navigation.
32 ## TODO: Find a better integration of oauth views into navigation.
33 <% my_account_oauth_url = h.route_path_or_none('my_account_oauth') %>
33 <% my_account_oauth_url = h.route_path_or_none('my_account_oauth') %>
34 % if my_account_oauth_url:
34 % if my_account_oauth_url:
35 <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li>
35 <li class="${'active' if c.active=='oauth' else ''}"><a href="${my_account_oauth_url}">${_('OAuth Identities')}</a></li>
36 % endif
36 % endif
37 <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('my_account_emails')}">${_('Emails')}</a></li>
37 <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('my_account_emails')}">${_('Emails')}</a></li>
38 <li class="${'active' if c.active=='repos' else ''}"><a href="${h.route_path('my_account_repos')}">${_('Repositories')}</a></li>
38 <li class="${'active' if c.active=='repos' else ''}"><a href="${h.route_path('my_account_repos')}">${_('Repositories')}</a></li>
39 <li class="${'active' if c.active=='watched' else ''}"><a href="${h.route_path('my_account_watched')}">${_('Watched')}</a></li>
39 <li class="${'active' if c.active=='watched' else ''}"><a href="${h.route_path('my_account_watched')}">${_('Watched')}</a></li>
40 <li class="${'active' if c.active=='pullrequests' else ''}"><a href="${h.url('my_account_pullrequests')}">${_('Pull Requests')}</a></li>
40 <li class="${'active' if c.active=='pullrequests' else ''}"><a href="${h.route_path('my_account_pullrequests')}">${_('Pull Requests')}</a></li>
41 <li class="${'active' if c.active=='perms' else ''}"><a href="${h.route_path('my_account_perms')}">${_('Permissions')}</a></li>
41 <li class="${'active' if c.active=='perms' else ''}"><a href="${h.route_path('my_account_perms')}">${_('Permissions')}</a></li>
42 <li class="${'active' if c.active=='my_notifications' else ''}"><a href="${h.route_path('my_account_notifications')}">${_('Live Notifications')}</a></li>
42 <li class="${'active' if c.active=='my_notifications' else ''}"><a href="${h.route_path('my_account_notifications')}">${_('Live Notifications')}</a></li>
43 </ul>
43 </ul>
44 </div>
44 </div>
45
45
46 <div class="main-content-full-width">
46 <div class="main-content-full-width">
47 <%include file="/admin/my_account/my_account_${c.active}.mako"/>
47 <%include file="/admin/my_account/my_account_${c.active}.mako"/>
48 </div>
48 </div>
49 </div>
49 </div>
50 </div>
50 </div>
51
51
52 </%def>
52 </%def>
@@ -1,55 +1,55 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2 <div class="panel panel-default user-profile">
2 <div class="panel panel-default user-profile">
3 <div class="panel-heading">
3 <div class="panel-heading">
4 <h3 class="panel-title">${_('My Profile')}</h3>
4 <h3 class="panel-title">${_('My Profile')}</h3>
5 <a href="${url('my_account_edit')}" class="panel-edit">${_('Edit')}</a>
5 <a href="${h.route_path('my_account_edit')}" class="panel-edit">${_('Edit')}</a>
6 </div>
6 </div>
7
7
8 <div class="panel-body">
8 <div class="panel-body">
9 <div class="fieldset">
9 <div class="fieldset">
10 <div class="left-label">
10 <div class="left-label">
11 ${_('Photo')}:
11 ${_('Photo')}:
12 </div>
12 </div>
13 <div class="right-content">
13 <div class="right-content">
14 %if c.visual.use_gravatar:
14 %if c.visual.use_gravatar:
15 ${base.gravatar(c.user.email, 100)}
15 ${base.gravatar(c.user.email, 100)}
16 %else:
16 %else:
17 ${base.gravatar(c.user.email, 20)}
17 ${base.gravatar(c.user.email, 20)}
18 ${_('Avatars are disabled')}
18 ${_('Avatars are disabled')}
19 %endif
19 %endif
20 </div>
20 </div>
21 </div>
21 </div>
22 <div class="fieldset">
22 <div class="fieldset">
23 <div class="left-label">
23 <div class="left-label">
24 ${_('Username')}:
24 ${_('Username')}:
25 </div>
25 </div>
26 <div class="right-content">
26 <div class="right-content">
27 ${c.user.username}
27 ${c.user.username}
28 </div>
28 </div>
29 </div>
29 </div>
30 <div class="fieldset">
30 <div class="fieldset">
31 <div class="left-label">
31 <div class="left-label">
32 ${_('First Name')}:
32 ${_('First Name')}:
33 </div>
33 </div>
34 <div class="right-content">
34 <div class="right-content">
35 ${c.user.first_name}
35 ${c.user.first_name}
36 </div>
36 </div>
37 </div>
37 </div>
38 <div class="fieldset">
38 <div class="fieldset">
39 <div class="left-label">
39 <div class="left-label">
40 ${_('Last Name')}:
40 ${_('Last Name')}:
41 </div>
41 </div>
42 <div class="right-content">
42 <div class="right-content">
43 ${c.user.last_name}
43 ${c.user.last_name}
44 </div>
44 </div>
45 </div>
45 </div>
46 <div class="fieldset">
46 <div class="fieldset">
47 <div class="left-label">
47 <div class="left-label">
48 ${_('Email')}:
48 ${_('Email')}:
49 </div>
49 </div>
50 <div class="right-content">
50 <div class="right-content">
51 ${c.user.email or _('Missing email, please update your user email address.')}
51 ${c.user.email or _('Missing email, please update your user email address.')}
52 </div>
52 </div>
53 </div>
53 </div>
54 </div>
54 </div>
55 </div> No newline at end of file
55 </div>
@@ -1,113 +1,113 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2 <div class="panel panel-default user-profile">
2 <div class="panel panel-default user-profile">
3 <div class="panel-heading">
3 <div class="panel-heading">
4 <h3 class="panel-title">${_('My Profile')}</h3>
4 <h3 class="panel-title">${_('My Profile')}</h3>
5 <a href="${h.route_path('my_account_profile')}" class="panel-edit">Close</a>
5 <a href="${h.route_path('my_account_profile')}" class="panel-edit">Close</a>
6 </div>
6 </div>
7
7
8 <div class="panel-body">
8 <div class="panel-body">
9 ${h.secure_form(url('my_account'), method='post', class_='form')}
9 ${h.secure_form(h.route_path('my_account_update'), class_='form', method='POST')}
10 <% readonly = None %>
10 <% readonly = None %>
11 <% disabled = "" %>
11 <% disabled = "" %>
12
12
13 % if c.extern_type != 'rhodecode':
13 % if c.extern_type != 'rhodecode':
14 <% readonly = "readonly" %>
14 <% readonly = "readonly" %>
15 <% disabled = "disabled" %>
15 <% disabled = "disabled" %>
16 <div class="infoform">
16 <div class="infoform">
17 <div class="fields">
17 <div class="fields">
18 <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')}
18 <p>${_('Your user account details are managed by an external source. Details cannot be managed here.')}
19 <br/>${_('Source type')}: <strong>${c.extern_type}</strong>
19 <br/>${_('Source type')}: <strong>${c.extern_type}</strong>
20 </p>
20 </p>
21
21
22 <div class="field">
22 <div class="field">
23 <div class="label">
23 <div class="label">
24 <label for="username">${_('Username')}:</label>
24 <label for="username">${_('Username')}:</label>
25 </div>
25 </div>
26 <div class="input">
26 <div class="input">
27 ${h.text('username', class_='input-valuedisplay', readonly=readonly)}
27 ${h.text('username', class_='input-valuedisplay', readonly=readonly)}
28 </div>
28 </div>
29 </div>
29 </div>
30
30
31 <div class="field">
31 <div class="field">
32 <div class="label">
32 <div class="label">
33 <label for="name">${_('First Name')}:</label>
33 <label for="name">${_('First Name')}:</label>
34 </div>
34 </div>
35 <div class="input">
35 <div class="input">
36 ${h.text('firstname', class_='input-valuedisplay', readonly=readonly)}
36 ${h.text('firstname', class_='input-valuedisplay', readonly=readonly)}
37 </div>
37 </div>
38 </div>
38 </div>
39
39
40 <div class="field">
40 <div class="field">
41 <div class="label">
41 <div class="label">
42 <label for="lastname">${_('Last Name')}:</label>
42 <label for="lastname">${_('Last Name')}:</label>
43 </div>
43 </div>
44 <div class="input-valuedisplay">
44 <div class="input-valuedisplay">
45 ${h.text('lastname', class_='input-valuedisplay', readonly=readonly)}
45 ${h.text('lastname', class_='input-valuedisplay', readonly=readonly)}
46 </div>
46 </div>
47 </div>
47 </div>
48 </div>
48 </div>
49 </div>
49 </div>
50 % else:
50 % else:
51 <div class="form">
51 <div class="form">
52 <div class="fields">
52 <div class="fields">
53 <div class="field">
53 <div class="field">
54 <div class="label photo">
54 <div class="label photo">
55 ${_('Photo')}:
55 ${_('Photo')}:
56 </div>
56 </div>
57 <div class="input profile">
57 <div class="input profile">
58 %if c.visual.use_gravatar:
58 %if c.visual.use_gravatar:
59 ${base.gravatar(c.user.email, 100)}
59 ${base.gravatar(c.user.email, 100)}
60 <p class="help-block">${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a>.</p>
60 <p class="help-block">${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a>.</p>
61 %else:
61 %else:
62 ${base.gravatar(c.user.email, 20)}
62 ${base.gravatar(c.user.email, 20)}
63 ${_('Avatars are disabled')}
63 ${_('Avatars are disabled')}
64 %endif
64 %endif
65 </div>
65 </div>
66 </div>
66 </div>
67 <div class="field">
67 <div class="field">
68 <div class="label">
68 <div class="label">
69 <label for="username">${_('Username')}:</label>
69 <label for="username">${_('Username')}:</label>
70 </div>
70 </div>
71 <div class="input">
71 <div class="input">
72 ${h.text('username', class_='medium%s' % disabled, readonly=readonly)}
72 ${h.text('username', class_='medium%s' % disabled, readonly=readonly)}
73 ${h.hidden('extern_name', c.extern_name)}
73 ${h.hidden('extern_name', c.extern_name)}
74 ${h.hidden('extern_type', c.extern_type)}
74 ${h.hidden('extern_type', c.extern_type)}
75 </div>
75 </div>
76 </div>
76 </div>
77 <div class="field">
77 <div class="field">
78 <div class="label">
78 <div class="label">
79 <label for="name">${_('First Name')}:</label>
79 <label for="name">${_('First Name')}:</label>
80 </div>
80 </div>
81 <div class="input">
81 <div class="input">
82 ${h.text('firstname', class_="medium")}
82 ${h.text('firstname', class_="medium")}
83 </div>
83 </div>
84 </div>
84 </div>
85
85
86 <div class="field">
86 <div class="field">
87 <div class="label">
87 <div class="label">
88 <label for="lastname">${_('Last Name')}:</label>
88 <label for="lastname">${_('Last Name')}:</label>
89 </div>
89 </div>
90 <div class="input">
90 <div class="input">
91 ${h.text('lastname', class_="medium")}
91 ${h.text('lastname', class_="medium")}
92 </div>
92 </div>
93 </div>
93 </div>
94
94
95 <div class="field">
95 <div class="field">
96 <div class="label">
96 <div class="label">
97 <label for="email">${_('Email')}:</label>
97 <label for="email">${_('Email')}:</label>
98 </div>
98 </div>
99 <div class="input">
99 <div class="input">
100 ## we should be able to edit email !
100 ## we should be able to edit email !
101 ${h.text('email', class_="medium")}
101 ${h.text('email', class_="medium")}
102 </div>
102 </div>
103 </div>
103 </div>
104
104
105 <div class="buttons">
105 <div class="buttons">
106 ${h.submit('save', _('Save'), class_="btn")}
106 ${h.submit('save', _('Save'), class_="btn")}
107 ${h.reset('reset', _('Reset'), class_="btn")}
107 ${h.reset('reset', _('Reset'), class_="btn")}
108 </div>
108 </div>
109 </div>
109 </div>
110 </div>
110 </div>
111 % endif
111 % endif
112 </div>
112 </div>
113 </div> No newline at end of file
113 </div>
@@ -1,78 +1,90 b''
1 <%namespace name="base" file="/base/base.mako"/>
1 <%namespace name="base" file="/base/base.mako"/>
2
2
3 <div class="panel panel-default">
3 <div class="panel panel-default">
4 <div class="panel-body">
4 <div class="panel-body">
5 %if c.show_closed:
5 %if c.closed:
6 ${h.checkbox('show_closed',checked="checked", label=_('Show Closed Pull Requests'))}
6 ${h.checkbox('show_closed',checked="checked", label=_('Show Closed Pull Requests'))}
7 %else:
7 %else:
8 ${h.checkbox('show_closed',label=_('Show Closed Pull Requests'))}
8 ${h.checkbox('show_closed',label=_('Show Closed Pull Requests'))}
9 %endif
9 %endif
10 </div>
10 </div>
11 </div>
11 </div>
12
12
13 <div class="panel panel-default">
13 <div class="panel panel-default">
14 <div class="panel-heading">
14 <div class="panel-heading">
15 <h3 class="panel-title">${_('Pull Requests You Participate In')}: ${c.records_total_participate}</h3>
15 <h3 class="panel-title">${_('Pull Requests You Participate In')}</h3>
16 </div>
16 </div>
17 <div class="panel-body">
17 <div class="panel-body panel-body-min-height">
18 <table id="pull_request_list_table_participate" class="display"></table>
18 <table id="pull_request_list_table" class="display"></table>
19 </div>
19 </div>
20 </div>
20 </div>
21
21
22 <script>
22 <script type="text/javascript">
23 $(document).ready(function() {
24
23 $('#show_closed').on('click', function(e){
25 $('#show_closed').on('click', function(e){
24 if($(this).is(":checked")){
26 if($(this).is(":checked")){
25 window.location = "${h.url('my_account_pullrequests', pr_show_closed=1)}";
27 window.location = "${h.route_path('my_account_pullrequests', _query={'pr_show_closed':1})}";
26 }
28 }
27 else{
29 else{
28 window.location = "${h.url('my_account_pullrequests')}";
30 window.location = "${h.route_path('my_account_pullrequests')}";
29 }
31 }
30 });
32 });
31 $(document).ready(function() {
33
34 var $pullRequestListTable = $('#pull_request_list_table');
32
35
33 var columnsDefs = [
36 // participating object list
37 $pullRequestListTable.DataTable({
38 processing: true,
39 serverSide: true,
40 ajax: {
41 "url": "${h.route_path('my_account_pullrequests_data')}",
42 "data": function (d) {
43 d.closed = "${c.closed}";
44 }
45 },
46 dom: 'rtp',
47 pageLength: ${c.visual.dashboard_items},
48 order: [[ 2, "desc" ]],
49 columns: [
34 { data: {"_": "status",
50 { data: {"_": "status",
35 "sort": "status"}, title: "", className: "td-status", orderable: false},
51 "sort": "status"}, title: "", className: "td-status", orderable: false},
36 { data: {"_": "target_repo",
52 { data: {"_": "target_repo",
37 "sort": "target_repo"}, title: "${_('Target Repo')}", className: "td-targetrepo", orderable: false},
53 "sort": "target_repo"}, title: "${_('Target Repo')}", className: "td-targetrepo", orderable: false},
38 { data: {"_": "name",
54 { data: {"_": "name",
39 "sort": "name_raw"}, title: "${_('Name')}", className: "td-componentname", "type": "num" },
55 "sort": "name_raw"}, title: "${_('Name')}", className: "td-componentname", "type": "num" },
40 { data: {"_": "author",
56 { data: {"_": "author",
41 "sort": "author_raw"}, title: "${_('Author')}", className: "td-user", orderable: false },
57 "sort": "author_raw"}, title: "${_('Author')}", className: "td-user", orderable: false },
42 { data: {"_": "title",
58 { data: {"_": "title",
43 "sort": "title"}, title: "${_('Title')}", className: "td-description" },
59 "sort": "title"}, title: "${_('Title')}", className: "td-description" },
44 { data: {"_": "comments",
60 { data: {"_": "comments",
45 "sort": "comments_raw"}, title: "", className: "td-comments", orderable: false},
61 "sort": "comments_raw"}, title: "", className: "td-comments", orderable: false},
46 { data: {"_": "updated_on",
62 { data: {"_": "updated_on",
47 "sort": "updated_on_raw"}, title: "${_('Last Update')}", className: "td-time" }
63 "sort": "updated_on_raw"}, title: "${_('Last Update')}", className: "td-time" }
48 ];
64 ],
49
50 // participating object list
51 $('#pull_request_list_table_participate').DataTable({
52 data: ${c.data_participate|n},
53 processing: true,
54 serverSide: true,
55 deferLoading: ${c.records_total_participate},
56 ajax: "",
57 dom: 'tp',
58 pageLength: ${c.visual.dashboard_items},
59 order: [[ 2, "desc" ]],
60 columns: columnsDefs,
61 language: {
65 language: {
62 paginate: DEFAULT_GRID_PAGINATION,
66 paginate: DEFAULT_GRID_PAGINATION,
67 sProcessing: _gettext('loading...'),
63 emptyTable: _gettext("There are currently no open pull requests requiring your participation.")
68 emptyTable: _gettext("There are currently no open pull requests requiring your participation.")
64 },
69 },
65 "drawCallback": function( settings, json ) {
70 "drawCallback": function( settings, json ) {
66 timeagoActivate();
71 timeagoActivate();
67 },
72 },
68 "createdRow": function ( row, data, index ) {
73 "createdRow": function ( row, data, index ) {
69 if (data['closed']) {
74 if (data['closed']) {
70 $(row).addClass('closed');
75 $(row).addClass('closed');
71 }
76 }
72 if (data['owned']) {
77 if (data['owned']) {
73 $(row).addClass('owned');
78 $(row).addClass('owned');
74 }
79 }
75 }
80 }
76 });
81 });
82 $pullRequestListTable.on('xhr.dt', function(e, settings, json, xhr){
83 $pullRequestListTable.css('opacity', 1);
84 });
85
86 $pullRequestListTable.on('preXhr.dt', function(e, settings, data){
87 $pullRequestListTable.css('opacity', 0.3);
88 });
77 });
89 });
78 </script>
90 </script>
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now