##// END OF EJS Templates
PEP8ify - controllers
marcink -
r1245:5f2fbab7 beta
parent child Browse files
Show More
@@ -1,57 +1,58
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.admin
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Controller for Admin panel of Rhodecode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27
28 28 from pylons import request, tmpl_context as c
29 29 from sqlalchemy.orm import joinedload
30 30 from webhelpers.paginate import Page
31 31
32 32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
33 33 from rhodecode.lib.base import BaseController, render
34 34 from rhodecode.model.db import UserLog
35 35
36 36 log = logging.getLogger(__name__)
37 37
38
38 39 class AdminController(BaseController):
39 40
40 41 @LoginRequired()
41 42 def __before__(self):
42 43 super(AdminController, self).__before__()
43 44
44 45 @HasPermissionAllDecorator('hg.admin')
45 46 def index(self):
46 47
47 48 users_log = self.sa.query(UserLog)\
48 49 .options(joinedload(UserLog.user))\
49 50 .options(joinedload(UserLog.repository))\
50 51 .order_by(UserLog.action_date.desc())
51 52
52 53 p = int(request.params.get('page', 1))
53 54 c.users_log = Page(users_log, page=p, items_per_page=10)
54 55 c.log_data = render('admin/admin_log.html')
55 56 if request.params.get('partial'):
56 57 return c.log_data
57 58 return render('admin/admin.html')
@@ -1,125 +1,124
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.ldap_settings
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 ldap controller for RhodeCode
7 7
8 8 :created_on: Nov 26, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25 import logging
26 26 import formencode
27 27 import traceback
28 28
29 29 from formencode import htmlfill
30 30
31 31 from pylons import request, response, session, tmpl_context as c, url
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons.i18n.translation import _
34 34
35 35 from rhodecode.lib.base import BaseController, render
36 36 from rhodecode.lib import helpers as h
37 37 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 38 from rhodecode.lib.auth_ldap import LdapImportError
39 39 from rhodecode.model.settings import SettingsModel
40 40 from rhodecode.model.forms import LdapSettingsForm
41 41 from sqlalchemy.exc import DatabaseError
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46
47 46 class LdapSettingsController(BaseController):
48 47
49 48 search_scope_choices = [('BASE', _('BASE'),),
50 49 ('ONELEVEL', _('ONELEVEL'),),
51 50 ('SUBTREE', _('SUBTREE'),),
52 51 ]
53 52 search_scope_default = 'SUBTREE'
54 53
55 54 tls_reqcert_choices = [('NEVER', _('NEVER'),),
56 55 ('ALLOW', _('ALLOW'),),
57 56 ('TRY', _('TRY'),),
58 57 ('DEMAND', _('DEMAND'),),
59 58 ('HARD', _('HARD'),),
60 59 ]
61 60 tls_reqcert_default = 'DEMAND'
62 61
63 62 @LoginRequired()
64 63 @HasPermissionAllDecorator('hg.admin')
65 64 def __before__(self):
66 65 c.admin_user = session.get('admin_user')
67 66 c.admin_username = session.get('admin_username')
68 67 c.search_scope_choices = self.search_scope_choices
69 68 c.tls_reqcert_choices = self.tls_reqcert_choices
70 69 super(LdapSettingsController, self).__before__()
71 70
72 71 def index(self):
73 72 defaults = SettingsModel().get_ldap_settings()
74 73 c.search_scope_cur = defaults.get('ldap_search_scope')
75 74 c.tls_reqcert_cur = defaults.get('ldap_tls_reqcert')
76 75
77 76 return htmlfill.render(
78 77 render('admin/ldap/ldap.html'),
79 78 defaults=defaults,
80 79 encoding="UTF-8",
81 80 force_defaults=True,)
82 81
83 82 def ldap_settings(self):
84 83 """POST ldap create and store ldap settings"""
85 84
86 85 settings_model = SettingsModel()
87 86 _form = LdapSettingsForm([x[0] for x in self.tls_reqcert_choices],
88 87 [x[0] for x in self.search_scope_choices])()
89 88
90 89 try:
91 90 form_result = _form.to_python(dict(request.POST))
92 91 try:
93 92
94 93 for k, v in form_result.items():
95 94 if k.startswith('ldap_'):
96 95 setting = settings_model.get(k)
97 96 setting.app_settings_value = v
98 97 self.sa.add(setting)
99 98
100 99 self.sa.commit()
101 100 h.flash(_('Ldap settings updated successfully'),
102 101 category='success')
103 102 except (DatabaseError,):
104 103 raise
105 104 except LdapImportError:
106 105 h.flash(_('Unable to activate ldap. The "python-ldap" library '
107 106 'is missing.'), category='warning')
108 107
109 108 except formencode.Invalid, errors:
110 109
111 110 c.search_scope_cur = self.search_scope_default
112 111 c.tls_reqcert_cur = self.search_scope_default
113 112
114 113 return htmlfill.render(
115 114 render('admin/ldap/ldap.html'),
116 115 defaults=errors.value,
117 116 errors=errors.error_dict or {},
118 117 prefix_error=False,
119 118 encoding="UTF-8")
120 119 except Exception:
121 120 log.error(traceback.format_exc())
122 121 h.flash(_('error occurred during update of ldap settings'),
123 122 category='error')
124 123
125 124 return redirect(url('ldap_home'))
@@ -1,169 +1,167
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.permissions
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 permissions controller for Rhodecode
7 7
8 8 :created_on: Apr 27, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 from formencode import htmlfill
27 27 from pylons import request, session, tmpl_context as c, url
28 28 from pylons.controllers.util import abort, redirect
29 29 from pylons.i18n.translation import _
30 30 from rhodecode.lib import helpers as h
31 31 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
32 32 from rhodecode.lib.auth_ldap import LdapImportError
33 33 from rhodecode.lib.base import BaseController, render
34 34 from rhodecode.model.forms import LdapSettingsForm, DefaultPermissionsForm
35 35 from rhodecode.model.permission import PermissionModel
36 36 from rhodecode.model.settings import SettingsModel
37 37 from rhodecode.model.user import UserModel
38 38 import formencode
39 39 import logging
40 40 import traceback
41 41
42 42 log = logging.getLogger(__name__)
43 43
44
44 45 class PermissionsController(BaseController):
45 46 """REST Controller styled on the Atom Publishing Protocol"""
46 47 # To properly map this controller, ensure your config/routing.py
47 48 # file has a resource setup:
48 49 # map.resource('permission', 'permissions')
49 50
50 51 @LoginRequired()
51 52 @HasPermissionAllDecorator('hg.admin')
52 53 def __before__(self):
53 54 c.admin_user = session.get('admin_user')
54 55 c.admin_username = session.get('admin_username')
55 56 super(PermissionsController, self).__before__()
56 57
57 58 self.perms_choices = [('repository.none', _('None'),),
58 59 ('repository.read', _('Read'),),
59 60 ('repository.write', _('Write'),),
60 61 ('repository.admin', _('Admin'),)]
61 62 self.register_choices = [
62 63 ('hg.register.none',
63 64 _('disabled')),
64 65 ('hg.register.manual_activate',
65 66 _('allowed with manual account activation')),
66 67 ('hg.register.auto_activate',
67 68 _('allowed with automatic account activation')), ]
68 69
69 70 self.create_choices = [('hg.create.none', _('Disabled')),
70 71 ('hg.create.repository', _('Enabled'))]
71 72
72
73 73 def index(self, format='html'):
74 74 """GET /permissions: All items in the collection"""
75 75 # url('permissions')
76 76
77 77 def create(self):
78 78 """POST /permissions: Create a new item"""
79 79 # url('permissions')
80 80
81 81 def new(self, format='html'):
82 82 """GET /permissions/new: Form to create a new item"""
83 83 # url('new_permission')
84 84
85 85 def update(self, id):
86 86 """PUT /permissions/id: Update an existing item"""
87 87 # Forms posted to this method should contain a hidden field:
88 88 # <input type="hidden" name="_method" value="PUT" />
89 89 # Or using helpers:
90 90 # h.form(url('permission', id=ID),
91 91 # method='put')
92 92 # url('permission', id=ID)
93 93
94 94 permission_model = PermissionModel()
95 95
96 96 _form = DefaultPermissionsForm([x[0] for x in self.perms_choices],
97 97 [x[0] for x in self.register_choices],
98 98 [x[0] for x in self.create_choices])()
99 99
100 100 try:
101 101 form_result = _form.to_python(dict(request.POST))
102 102 form_result.update({'perm_user_name':id})
103 103 permission_model.update(form_result)
104 104 h.flash(_('Default permissions updated successfully'),
105 105 category='success')
106 106
107 107 except formencode.Invalid, errors:
108 108 c.perms_choices = self.perms_choices
109 109 c.register_choices = self.register_choices
110 110 c.create_choices = self.create_choices
111 111 defaults = errors.value
112 112
113 113 return htmlfill.render(
114 114 render('admin/permissions/permissions.html'),
115 115 defaults=defaults,
116 116 errors=errors.error_dict or {},
117 117 prefix_error=False,
118 118 encoding="UTF-8")
119 119 except Exception:
120 120 log.error(traceback.format_exc())
121 121 h.flash(_('error occurred during update of permissions'),
122 122 category='error')
123 123
124 124 return redirect(url('edit_permission', id=id))
125 125
126
127
128 126 def delete(self, id):
129 127 """DELETE /permissions/id: Delete an existing item"""
130 128 # Forms posted to this method should contain a hidden field:
131 129 # <input type="hidden" name="_method" value="DELETE" />
132 130 # Or using helpers:
133 131 # h.form(url('permission', id=ID),
134 132 # method='delete')
135 133 # url('permission', id=ID)
136 134
137 135 def show(self, id, format='html'):
138 136 """GET /permissions/id: Show a specific item"""
139 137 # url('permission', id=ID)
140 138
141 139 def edit(self, id, format='html'):
142 140 """GET /permissions/id/edit: Form to edit an existing item"""
143 141 #url('edit_permission', id=ID)
144 142 c.perms_choices = self.perms_choices
145 143 c.register_choices = self.register_choices
146 144 c.create_choices = self.create_choices
147 145
148 146 if id == 'default':
149 147 default_user = UserModel().get_by_username('default')
150 148 defaults = {'_method':'put',
151 149 'anonymous':default_user.active}
152 150
153 151 for p in default_user.user_perms:
154 152 if p.permission.permission_name.startswith('repository.'):
155 153 defaults['default_perm'] = p.permission.permission_name
156 154
157 155 if p.permission.permission_name.startswith('hg.register.'):
158 156 defaults['default_register'] = p.permission.permission_name
159 157
160 158 if p.permission.permission_name.startswith('hg.create.'):
161 159 defaults['default_create'] = p.permission.permission_name
162 160
163 161 return htmlfill.render(
164 162 render('admin/permissions/permissions.html'),
165 163 defaults=defaults,
166 164 encoding="UTF-8",
167 165 force_defaults=True,)
168 166 else:
169 167 return redirect(url('admin_home'))
@@ -1,421 +1,415
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.repos
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Admin controller for RhodeCode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29 from operator import itemgetter
30 30 from formencode import htmlfill
31 31
32 32 from paste.httpexceptions import HTTPInternalServerError
33 33 from pylons import request, response, session, tmpl_context as c, url
34 34 from pylons.controllers.util import abort, redirect
35 35 from pylons.i18n.translation import _
36 36
37 37 from rhodecode.lib import helpers as h
38 38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
39 39 HasPermissionAnyDecorator
40 40 from rhodecode.lib.base import BaseController, render
41 41 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
42 42 from rhodecode.lib.helpers import get_token
43 43 from rhodecode.model.db import User, Repository, UserFollowing, Group
44 44 from rhodecode.model.forms import RepoForm
45 45 from rhodecode.model.scm import ScmModel
46 46 from rhodecode.model.repo import RepoModel
47 47
48 48 log = logging.getLogger(__name__)
49 49
50
50 51 class ReposController(BaseController):
51 52 """
52 53 REST Controller styled on the Atom Publishing Protocol"""
53 54 # To properly map this controller, ensure your config/routing.py
54 55 # file has a resource setup:
55 56 # map.resource('repo', 'repos')
56 57
57 58 @LoginRequired()
58 59 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
59 60 def __before__(self):
60 61 c.admin_user = session.get('admin_user')
61 62 c.admin_username = session.get('admin_username')
62 63 super(ReposController, self).__before__()
63 64
64 65 def __load_defaults(self):
65 66 repo_model = RepoModel()
66 67
67 68 c.repo_groups = [('', '')]
68 69 parents_link = lambda k:h.literal('&raquo;'.join(
69 70 map(lambda k:k.group_name,
70 71 k.parents + [k])
71 72 )
72 73 )
73 74
74 75 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
75 76 x in self.sa.query(Group).all()])
76 77 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
77 78 c.users_array = repo_model.get_users_js()
78 79 c.users_groups_array = repo_model.get_users_groups_js()
79 80
80 81 def __load_data(self, repo_name=None):
81 82 """
82 83 Load defaults settings for edit, and update
83 84
84 85 :param repo_name:
85 86 """
86 87 self.__load_defaults()
87 88
88 89 repo, dbrepo = ScmModel().get(repo_name, retval='repo')
89 90
90 91 repo_model = RepoModel()
91 92 c.repo_info = repo_model.get_by_repo_name(repo_name)
92 93
93
94 94 if c.repo_info is None:
95 95 h.flash(_('%s repository is not mapped to db perhaps'
96 96 ' it was created or renamed from the filesystem'
97 97 ' please run the application again'
98 98 ' in order to rescan repositories') % repo_name,
99 99 category='error')
100 100
101 101 return redirect(url('repos'))
102 102
103
104 103 c.default_user_id = User.by_username('default').user_id
105 104 c.in_public_journal = self.sa.query(UserFollowing)\
106 105 .filter(UserFollowing.user_id == c.default_user_id)\
107 106 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
108 107
109 108 if c.repo_info.stats:
110 109 last_rev = c.repo_info.stats.stat_on_revision
111 110 else:
112 111 last_rev = 0
113 112 c.stats_revision = last_rev
114 113
115 114 c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
116 115
117 116 if last_rev == 0 or c.repo_last_rev == 0:
118 117 c.stats_percentage = 0
119 118 else:
120 119 c.stats_percentage = '%.2f' % ((float((last_rev)) /
121 120 c.repo_last_rev) * 100)
122 121
123
124
125 122 defaults = c.repo_info.get_dict()
126 123 group, repo_name = c.repo_info.groups_and_repo
127 124 defaults['repo_name'] = repo_name
128 125 defaults['repo_group'] = getattr(group[-1] if group else None,
129 126 'group_id', None)
130 127
131 128 #fill owner
132 129 if c.repo_info.user:
133 130 defaults.update({'user':c.repo_info.user.username})
134 131 else:
135 132 replacement_user = self.sa.query(User)\
136 133 .filter(User.admin == True).first().username
137 134 defaults.update({'user':replacement_user})
138 135
139
140 136 #fill repository users
141 137 for p in c.repo_info.repo_to_perm:
142 138 defaults.update({'u_perm_%s' % p.user.username:
143 139 p.permission.permission_name})
144 140
145 141 #fill repository groups
146 142 for p in c.repo_info.users_group_to_perm:
147 143 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
148 144 p.permission.permission_name})
149 145
150
151 146 return defaults
152 147
153
154 148 @HasPermissionAllDecorator('hg.admin')
155 149 def index(self, format='html'):
156 150 """GET /repos: All items in the collection"""
157 151 # url('repos')
158 152 cached_repo_list = ScmModel().get_repos()
159 153 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
160 154 return render('admin/repos/repos.html')
161 155
162 156 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
163 157 def create(self):
164 158 """
165 159 POST /repos: Create a new item"""
166 160 # url('repos')
167 161 repo_model = RepoModel()
168 162 self.__load_defaults()
169 163 form_result = {}
170 164 try:
171 165 form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
172 166 .to_python(dict(request.POST))
173 167 repo_model.create(form_result, self.rhodecode_user)
174 168 if form_result['clone_uri']:
175 169 h.flash(_('created repository %s from %s') \
176 170 % (form_result['repo_name'], form_result['clone_uri']),
177 171 category='success')
178 172 else:
179 173 h.flash(_('created repository %s') % form_result['repo_name'],
180 174 category='success')
181 175
182 176 if request.POST.get('user_created'):
183 177 action_logger(self.rhodecode_user, 'user_created_repo',
184 178 form_result['repo_name'], '', self.sa)
185 179 else:
186 180 action_logger(self.rhodecode_user, 'admin_created_repo',
187 181 form_result['repo_name'], '', self.sa)
188 182
189 183 except formencode.Invalid, errors:
190 184
191 185 c.new_repo = errors.value['repo_name']
192 186
193 187 if request.POST.get('user_created'):
194 188 r = render('admin/repos/repo_add_create_repository.html')
195 189 else:
196 190 r = render('admin/repos/repo_add.html')
197 191
198 192 return htmlfill.render(
199 193 r,
200 194 defaults=errors.value,
201 195 errors=errors.error_dict or {},
202 196 prefix_error=False,
203 197 encoding="UTF-8")
204 198
205 199 except Exception:
206 200 log.error(traceback.format_exc())
207 201 msg = _('error occurred during creation of repository %s') \
208 202 % form_result.get('repo_name')
209 203 h.flash(msg, category='error')
210 204 if request.POST.get('user_created'):
211 205 return redirect(url('home'))
212 206 return redirect(url('repos'))
213 207
214 208 @HasPermissionAllDecorator('hg.admin')
215 209 def new(self, format='html'):
216 210 """GET /repos/new: Form to create a new item"""
217 211 new_repo = request.GET.get('repo', '')
218 212 c.new_repo = repo_name_slug(new_repo)
219 213 self.__load_defaults()
220 214 return render('admin/repos/repo_add.html')
221 215
222 216 @HasPermissionAllDecorator('hg.admin')
223 217 def update(self, repo_name):
224 218 """
225 219 PUT /repos/repo_name: Update an existing item"""
226 220 # Forms posted to this method should contain a hidden field:
227 221 # <input type="hidden" name="_method" value="PUT" />
228 222 # Or using helpers:
229 223 # h.form(url('repo', repo_name=ID),
230 224 # method='put')
231 225 # url('repo', repo_name=ID)
232 226 self.__load_defaults()
233 227 repo_model = RepoModel()
234 228 changed_name = repo_name
235 229 _form = RepoForm(edit=True, old_data={'repo_name':repo_name},
236 230 repo_groups=c.repo_groups_choices)()
237 231 try:
238 232 form_result = _form.to_python(dict(request.POST))
239 233 repo_model.update(repo_name, form_result)
240 234 invalidate_cache('get_repo_cached_%s' % repo_name)
241 235 h.flash(_('Repository %s updated successfully' % repo_name),
242 236 category='success')
243 237 changed_name = form_result['repo_name']
244 238 action_logger(self.rhodecode_user, 'admin_updated_repo',
245 239 changed_name, '', self.sa)
246 240
247 241 except formencode.Invalid, errors:
248 242 defaults = self.__load_data(repo_name)
249 243 defaults.update(errors.value)
250 244 return htmlfill.render(
251 245 render('admin/repos/repo_edit.html'),
252 246 defaults=defaults,
253 247 errors=errors.error_dict or {},
254 248 prefix_error=False,
255 249 encoding="UTF-8")
256 250
257 251 except Exception:
258 252 log.error(traceback.format_exc())
259 253 h.flash(_('error occurred during update of repository %s') \
260 254 % repo_name, category='error')
261 255 return redirect(url('edit_repo', repo_name=changed_name))
262 256
263 257 @HasPermissionAllDecorator('hg.admin')
264 258 def delete(self, repo_name):
265 259 """
266 260 DELETE /repos/repo_name: Delete an existing item"""
267 261 # Forms posted to this method should contain a hidden field:
268 262 # <input type="hidden" name="_method" value="DELETE" />
269 263 # Or using helpers:
270 264 # h.form(url('repo', repo_name=ID),
271 265 # method='delete')
272 266 # url('repo', repo_name=ID)
273 267
274 268 repo_model = RepoModel()
275 269 repo = repo_model.get_by_repo_name(repo_name)
276 270 if not repo:
277 271 h.flash(_('%s repository is not mapped to db perhaps'
278 272 ' it was moved or renamed from the filesystem'
279 273 ' please run the application again'
280 274 ' in order to rescan repositories') % repo_name,
281 275 category='error')
282 276
283 277 return redirect(url('repos'))
284 278 try:
285 279 action_logger(self.rhodecode_user, 'admin_deleted_repo',
286 280 repo_name, '', self.sa)
287 281 repo_model.delete(repo)
288 282 invalidate_cache('get_repo_cached_%s' % repo_name)
289 283 h.flash(_('deleted repository %s') % repo_name, category='success')
290 284
291 285 except Exception, e:
292 286 log.error(traceback.format_exc())
293 287 h.flash(_('An error occurred during deletion of %s') % repo_name,
294 288 category='error')
295 289
296 290 return redirect(url('repos'))
297 291
298 292 @HasPermissionAllDecorator('hg.admin')
299 293 def delete_perm_user(self, repo_name):
300 294 """
301 295 DELETE an existing repository permission user
302 296
303 297 :param repo_name:
304 298 """
305 299
306 300 try:
307 301 repo_model = RepoModel()
308 302 repo_model.delete_perm_user(request.POST, repo_name)
309 303 except Exception, e:
310 304 h.flash(_('An error occurred during deletion of repository user'),
311 305 category='error')
312 306 raise HTTPInternalServerError()
313 307
314 308 @HasPermissionAllDecorator('hg.admin')
315 309 def delete_perm_users_group(self, repo_name):
316 310 """
317 311 DELETE an existing repository permission users group
318 312
319 313 :param repo_name:
320 314 """
321 315 try:
322 316 repo_model = RepoModel()
323 317 repo_model.delete_perm_users_group(request.POST, repo_name)
324 318 except Exception, e:
325 319 h.flash(_('An error occurred during deletion of repository'
326 320 ' users groups'),
327 321 category='error')
328 322 raise HTTPInternalServerError()
329 323
330 324 @HasPermissionAllDecorator('hg.admin')
331 325 def repo_stats(self, repo_name):
332 326 """
333 327 DELETE an existing repository statistics
334 328
335 329 :param repo_name:
336 330 """
337 331
338 332 try:
339 333 repo_model = RepoModel()
340 334 repo_model.delete_stats(repo_name)
341 335 except Exception, e:
342 336 h.flash(_('An error occurred during deletion of repository stats'),
343 337 category='error')
344 338 return redirect(url('edit_repo', repo_name=repo_name))
345 339
346 340 @HasPermissionAllDecorator('hg.admin')
347 341 def repo_cache(self, repo_name):
348 342 """
349 343 INVALIDATE existing repository cache
350 344
351 345 :param repo_name:
352 346 """
353 347
354 348 try:
355 349 ScmModel().mark_for_invalidation(repo_name)
356 350 except Exception, e:
357 351 h.flash(_('An error occurred during cache invalidation'),
358 352 category='error')
359 353 return redirect(url('edit_repo', repo_name=repo_name))
360 354
361 355 @HasPermissionAllDecorator('hg.admin')
362 356 def repo_public_journal(self, repo_name):
363 357 """
364 358 Set's this repository to be visible in public journal,
365 359 in other words assing default user to follow this repo
366 360
367 361 :param repo_name:
368 362 """
369 363
370 364 cur_token = request.POST.get('auth_token')
371 365 token = get_token()
372 366 if cur_token == token:
373 367 try:
374 368 repo_id = Repository.by_repo_name(repo_name).repo_id
375 369 user_id = User.by_username('default').user_id
376 370 self.scm_model.toggle_following_repo(repo_id, user_id)
377 371 h.flash(_('Updated repository visibility in public journal'),
378 372 category='success')
379 373 except:
380 374 h.flash(_('An error occurred during setting this'
381 375 ' repository in public journal'),
382 376 category='error')
383 377
384 378 else:
385 379 h.flash(_('Token mismatch'), category='error')
386 380 return redirect(url('edit_repo', repo_name=repo_name))
387 381
388 382 @HasPermissionAllDecorator('hg.admin')
389 383 def repo_pull(self, repo_name):
390 384 """
391 385 Runs task to update given repository with remote changes,
392 386 ie. make pull on remote location
393 387
394 388 :param repo_name:
395 389 """
396 390 try:
397 391 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
398 392 h.flash(_('Pulled from remote location'), category='success')
399 393 except Exception, e:
400 394 h.flash(_('An error occurred during pull from remote location'),
401 395 category='error')
402 396
403 397 return redirect(url('edit_repo', repo_name=repo_name))
404 398
405 399 @HasPermissionAllDecorator('hg.admin')
406 400 def show(self, repo_name, format='html'):
407 401 """GET /repos/repo_name: Show a specific item"""
408 402 # url('repo', repo_name=ID)
409 403
410 404 @HasPermissionAllDecorator('hg.admin')
411 405 def edit(self, repo_name, format='html'):
412 406 """GET /repos/repo_name/edit: Form to edit an existing item"""
413 407 # url('edit_repo', repo_name=ID)
414 408 defaults = self.__load_data(repo_name)
415 409
416 410 return htmlfill.render(
417 411 render('admin/repos/repo_edit.html'),
418 412 defaults=defaults,
419 413 encoding="UTF-8",
420 414 force_defaults=False
421 415 )
@@ -1,91 +1,89
1 1 import logging
2 2 from operator import itemgetter
3 3
4 4 from pylons import request, response, session, tmpl_context as c, url
5 5 from pylons.controllers.util import abort, redirect
6 6
7 7 from rhodecode.lib.base import BaseController, render
8 8 from rhodecode.model.db import Group
9 9
10 10 log = logging.getLogger(__name__)
11 11
12
12 13 class ReposGroupsController(BaseController):
13 14 """REST Controller styled on the Atom Publishing Protocol"""
14 15 # To properly map this controller, ensure your config/routing.py
15 16 # file has a resource setup:
16 17 # map.resource('repos_group', 'repos_groups')
17 18
18 19 def index(self, format='html'):
19 20 """GET /repos_groups: All items in the collection"""
20 21 # url('repos_groups')
21 22
22 23 def create(self):
23 24 """POST /repos_groups: Create a new item"""
24 25 # url('repos_groups')
25 26
26 27 def new(self, format='html'):
27 28 """GET /repos_groups/new: Form to create a new item"""
28 29 # url('new_repos_group')
29 30
30 31 def update(self, id):
31 32 """PUT /repos_groups/id: Update an existing item"""
32 33 # Forms posted to this method should contain a hidden field:
33 34 # <input type="hidden" name="_method" value="PUT" />
34 35 # Or using helpers:
35 36 # h.form(url('repos_group', id=ID),
36 37 # method='put')
37 38 # url('repos_group', id=ID)
38 39
39 40 def delete(self, id):
40 41 """DELETE /repos_groups/id: Delete an existing item"""
41 42 # Forms posted to this method should contain a hidden field:
42 43 # <input type="hidden" name="_method" value="DELETE" />
43 44 # Or using helpers:
44 45 # h.form(url('repos_group', id=ID),
45 46 # method='delete')
46 47 # url('repos_group', id=ID)
47 48
48 49 def show(self, id, format='html'):
49 50 """GET /repos_groups/id: Show a specific item"""
50 51 # url('repos_group', id=ID)
51 52
52 53 c.group = Group.get(id)
53 54 if c.group:
54 55 c.group_repos = c.group.repositories
55 56 else:
56 57 return redirect(url('repos_group'))
57 58
58 59 sortables = ['name', 'description', 'last_change', 'tip', 'owner']
59 60 current_sort = request.GET.get('sort', 'name')
60 61 current_sort_slug = current_sort.replace('-', '')
61 62
62 63 if current_sort_slug not in sortables:
63 64 c.sort_by = 'name'
64 65 current_sort_slug = c.sort_by
65 66 else:
66 67 c.sort_by = current_sort
67 68 c.sort_slug = current_sort_slug
68 69
69 70 sort_key = current_sort_slug + '_sort'
70 71
71
72 72 #overwrite our cached list with current filter
73 73 gr_filter = [r.repo_name for r in c.group_repos]
74 74 c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter)
75 75
76 76 if c.sort_by.startswith('-'):
77 77 c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key),
78 78 reverse=True)
79 79 else:
80 80 c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key),
81 81 reverse=False)
82 82
83 83 c.repo_cnt = len(c.repos_list)
84 84
85
86 85 return render('admin/repos_groups/repos_groups.html')
87 86
88
89 87 def edit(self, id, format='html'):
90 88 """GET /repos_groups/id/edit: Form to edit an existing item"""
91 89 # url('edit_repos_group', id=ID)
@@ -1,357 +1,363
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.settings
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 settings controller for rhodecode admin
7 7
8 8 :created_on: Jul 14, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29
30 30 from sqlalchemy import func
31 31 from formencode import htmlfill
32 32 from pylons import request, session, tmpl_context as c, url, config
33 33 from pylons.controllers.util import abort, redirect
34 34 from pylons.i18n.translation import _
35 35
36 36 from rhodecode.lib import helpers as h
37 37 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
38 38 HasPermissionAnyDecorator, NotAnonymous
39 39 from rhodecode.lib.base import BaseController, render
40 40 from rhodecode.lib.celerylib import tasks, run_task
41 41 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
42 42 set_rhodecode_config, repo_name_slug
43 43 from rhodecode.model.db import RhodeCodeUi, Repository, Group
44 44 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
45 45 ApplicationUiSettingsForm
46 46 from rhodecode.model.scm import ScmModel
47 47 from rhodecode.model.settings import SettingsModel
48 48 from rhodecode.model.user import UserModel
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52
53 53 class SettingsController(BaseController):
54 54 """REST Controller styled on the Atom Publishing Protocol"""
55 55 # To properly map this controller, ensure your config/routing.py
56 56 # file has a resource setup:
57 57 # map.resource('setting', 'settings', controller='admin/settings',
58 58 # path_prefix='/admin', name_prefix='admin_')
59 59
60
61 60 @LoginRequired()
62 61 def __before__(self):
63 62 c.admin_user = session.get('admin_user')
64 63 c.admin_username = session.get('admin_username')
65 64 super(SettingsController, self).__before__()
66 65
67
68 66 @HasPermissionAllDecorator('hg.admin')
69 67 def index(self, format='html'):
70 68 """GET /admin/settings: All items in the collection"""
71 69 # url('admin_settings')
72 70
73 71 defaults = SettingsModel().get_app_settings()
74 72 defaults.update(self.get_hg_ui_settings())
75 73 return htmlfill.render(
76 74 render('admin/settings/settings.html'),
77 75 defaults=defaults,
78 76 encoding="UTF-8",
79 77 force_defaults=False
80 78 )
81 79
82 80 @HasPermissionAllDecorator('hg.admin')
83 81 def create(self):
84 82 """POST /admin/settings: Create a new item"""
85 83 # url('admin_settings')
86 84
87 85 @HasPermissionAllDecorator('hg.admin')
88 86 def new(self, format='html'):
89 87 """GET /admin/settings/new: Form to create a new item"""
90 88 # url('admin_new_setting')
91 89
92 90 @HasPermissionAllDecorator('hg.admin')
93 91 def update(self, setting_id):
94 92 """PUT /admin/settings/setting_id: Update an existing item"""
95 93 # Forms posted to this method should contain a hidden field:
96 94 # <input type="hidden" name="_method" value="PUT" />
97 95 # Or using helpers:
98 96 # h.form(url('admin_setting', setting_id=ID),
99 97 # method='put')
100 98 # url('admin_setting', setting_id=ID)
101 99 if setting_id == 'mapping':
102 100 rm_obsolete = request.POST.get('destroy', False)
103 101 log.debug('Rescanning directories with destroy=%s', rm_obsolete)
104 102 initial = ScmModel().repo_scan()
105 103 log.debug('invalidating all repositories')
106 104 for repo_name in initial.keys():
107 105 invalidate_cache('get_repo_cached_%s' % repo_name)
108 106
109 107 added, removed = repo2db_mapper(initial, rm_obsolete)
110 108
111 109 h.flash(_('Repositories successfully'
112 ' rescanned added: %s,removed: %s') % (added, removed)
113 , category='success')
110 ' rescanned added: %s,removed: %s') % (added, removed),
111 category='success')
114 112
115 113 if setting_id == 'whoosh':
116 114 repo_location = self.get_hg_ui_settings()['paths_root_path']
117 115 full_index = request.POST.get('full_index', False)
118 116 run_task(tasks.whoosh_index, repo_location, full_index)
119 117
120 118 h.flash(_('Whoosh reindex task scheduled'), category='success')
121 119 if setting_id == 'global':
122 120
123 121 application_form = ApplicationSettingsForm()()
124 122 try:
125 123 form_result = application_form.to_python(dict(request.POST))
126 124 settings_model = SettingsModel()
127 125
128 126 try:
129 127 hgsettings1 = settings_model.get('title')
130 hgsettings1.app_settings_value = form_result['rhodecode_title']
128 hgsettings1.app_settings_value = \
129 form_result['rhodecode_title']
131 130
132 131 hgsettings2 = settings_model.get('realm')
133 hgsettings2.app_settings_value = form_result['rhodecode_realm']
132 hgsettings2.app_settings_value = \
133 form_result['rhodecode_realm']
134 134
135 135 hgsettings3 = settings_model.get('ga_code')
136 hgsettings3.app_settings_value = form_result['rhodecode_ga_code']
137
138
136 hgsettings3.app_settings_value = \
137 form_result['rhodecode_ga_code']
139 138
140 139 self.sa.add(hgsettings1)
141 140 self.sa.add(hgsettings2)
142 141 self.sa.add(hgsettings3)
143 142 self.sa.commit()
144 143 set_rhodecode_config(config)
145 144 h.flash(_('Updated application settings'),
146 145 category='success')
147 146
148 147 except Exception:
149 148 log.error(traceback.format_exc())
150 h.flash(_('error occurred during updating application settings'),
149 h.flash(_('error occurred during updating '
150 'application settings'),
151 151 category='error')
152 152
153 153 self.sa.rollback()
154 154
155
156 155 except formencode.Invalid, errors:
157 156 return htmlfill.render(
158 157 render('admin/settings/settings.html'),
159 158 defaults=errors.value,
160 159 errors=errors.error_dict or {},
161 160 prefix_error=False,
162 161 encoding="UTF-8")
163 162
164 163 if setting_id == 'mercurial':
165 164 application_form = ApplicationUiSettingsForm()()
166 165 try:
167 166 form_result = application_form.to_python(dict(request.POST))
168 167
169 168 try:
170 169
171 170 hgsettings1 = self.sa.query(RhodeCodeUi)\
172 171 .filter(RhodeCodeUi.ui_key == 'push_ssl').one()
173 172 hgsettings1.ui_value = form_result['web_push_ssl']
174 173
175 174 hgsettings2 = self.sa.query(RhodeCodeUi)\
176 175 .filter(RhodeCodeUi.ui_key == '/').one()
177 176 hgsettings2.ui_value = form_result['paths_root_path']
178 177
179
180 178 #HOOKS
181 179 hgsettings3 = self.sa.query(RhodeCodeUi)\
182 180 .filter(RhodeCodeUi.ui_key == 'changegroup.update').one()
183 hgsettings3.ui_active = bool(form_result['hooks_changegroup_update'])
181 hgsettings3.ui_active = \
182 bool(form_result['hooks_changegroup_update'])
184 183
185 184 hgsettings4 = self.sa.query(RhodeCodeUi)\
186 .filter(RhodeCodeUi.ui_key == 'changegroup.repo_size').one()
187 hgsettings4.ui_active = bool(form_result['hooks_changegroup_repo_size'])
185 .filter(RhodeCodeUi.ui_key ==
186 'changegroup.repo_size').one()
187 hgsettings4.ui_active = \
188 bool(form_result['hooks_changegroup_repo_size'])
188 189
189 190 hgsettings5 = self.sa.query(RhodeCodeUi)\
190 .filter(RhodeCodeUi.ui_key == 'pretxnchangegroup.push_logger').one()
191 hgsettings5.ui_active = bool(form_result['hooks_pretxnchangegroup_push_logger'])
191 .filter(RhodeCodeUi.ui_key ==
192 'pretxnchangegroup.push_logger').one()
193 hgsettings5.ui_active = \
194 bool(form_result['hooks_pretxnchangegroup'
195 '_push_logger'])
192 196
193 197 hgsettings6 = self.sa.query(RhodeCodeUi)\
194 .filter(RhodeCodeUi.ui_key == 'preoutgoing.pull_logger').one()
195 hgsettings6.ui_active = bool(form_result['hooks_preoutgoing_pull_logger'])
196
198 .filter(RhodeCodeUi.ui_key ==
199 'preoutgoing.pull_logger').one()
200 hgsettings6.ui_active = \
201 bool(form_result['hooks_preoutgoing_pull_logger'])
197 202
198 203 self.sa.add(hgsettings1)
199 204 self.sa.add(hgsettings2)
200 205 self.sa.add(hgsettings3)
201 206 self.sa.add(hgsettings4)
202 207 self.sa.add(hgsettings5)
203 208 self.sa.add(hgsettings6)
204 209 self.sa.commit()
205 210
206 211 h.flash(_('Updated mercurial settings'),
207 212 category='success')
208 213
209 214 except:
210 215 log.error(traceback.format_exc())
211 h.flash(_('error occurred during updating application settings'),
212 category='error')
216 h.flash(_('error occurred during updating '
217 'application settings'), category='error')
213 218
214 219 self.sa.rollback()
215 220
216
217 221 except formencode.Invalid, errors:
218 222 return htmlfill.render(
219 223 render('admin/settings/settings.html'),
220 224 defaults=errors.value,
221 225 errors=errors.error_dict or {},
222 226 prefix_error=False,
223 227 encoding="UTF-8")
224 228
225
226
227 229 return redirect(url('admin_settings'))
228 230
229 231 @HasPermissionAllDecorator('hg.admin')
230 232 def delete(self, setting_id):
231 233 """DELETE /admin/settings/setting_id: Delete an existing item"""
232 234 # Forms posted to this method should contain a hidden field:
233 235 # <input type="hidden" name="_method" value="DELETE" />
234 236 # Or using helpers:
235 237 # h.form(url('admin_setting', setting_id=ID),
236 238 # method='delete')
237 239 # url('admin_setting', setting_id=ID)
238 240
239 241 @HasPermissionAllDecorator('hg.admin')
240 242 def show(self, setting_id, format='html'):
241 """GET /admin/settings/setting_id: Show a specific item"""
243 """
244 GET /admin/settings/setting_id: Show a specific item"""
242 245 # url('admin_setting', setting_id=ID)
243 246
244 247 @HasPermissionAllDecorator('hg.admin')
245 248 def edit(self, setting_id, format='html'):
246 """GET /admin/settings/setting_id/edit: Form to edit an existing item"""
249 """
250 GET /admin/settings/setting_id/edit: Form to
251 edit an existing item"""
247 252 # url('admin_edit_setting', setting_id=ID)
248 253
249 254 @NotAnonymous()
250 255 def my_account(self):
251 256 """
252 257 GET /_admin/my_account Displays info about my account
253 258 """
254 259 # url('admin_settings_my_account')
255 260
256 261 c.user = UserModel().get(self.rhodecode_user.user_id, cache=False)
257 262 all_repos = [r.repo_name for r in self.sa.query(Repository)\
258 263 .filter(Repository.user_id == c.user.user_id)\
259 264 .order_by(func.lower(Repository.repo_name)).all()]
260 265 c.user_repos = ScmModel().get_repos(all_repos)
261 266
262 267 if c.user.username == 'default':
263 268 h.flash(_("You can't edit this user since it's"
264 269 " crucial for entire application"), category='warning')
265 270 return redirect(url('users'))
266 271
267 272 defaults = c.user.get_dict()
268 273 return htmlfill.render(
269 274 render('admin/users/user_edit_my_account.html'),
270 275 defaults=defaults,
271 276 encoding="UTF-8",
272 277 force_defaults=False
273 278 )
274 279
275 280 def my_account_update(self):
276 281 """PUT /_admin/my_account_update: Update an existing item"""
277 282 # Forms posted to this method should contain a hidden field:
278 283 # <input type="hidden" name="_method" value="PUT" />
279 284 # Or using helpers:
280 285 # h.form(url('admin_settings_my_account_update'),
281 286 # method='put')
282 287 # url('admin_settings_my_account_update', id=ID)
283 288 user_model = UserModel()
284 289 uid = self.rhodecode_user.user_id
285 _form = UserForm(edit=True, old_data={'user_id':uid,
290 _form = UserForm(edit=True,
291 old_data={'user_id': uid,
286 292 'email':self.rhodecode_user.email})()
287 293 form_result = {}
288 294 try:
289 295 form_result = _form.to_python(dict(request.POST))
290 296 user_model.update_my_account(uid, form_result)
291 297 h.flash(_('Your account was updated successfully'),
292 298 category='success')
293 299
294 300 except formencode.Invalid, errors:
295 301 c.user = user_model.get(self.rhodecode_user.user_id, cache=False)
296 302 c.user = UserModel().get(self.rhodecode_user.user_id, cache=False)
297 303 all_repos = self.sa.query(Repository)\
298 304 .filter(Repository.user_id == c.user.user_id)\
299 305 .order_by(func.lower(Repository.repo_name))\
300 306 .all()
301 307 c.user_repos = ScmModel().get_repos(all_repos)
302 308
303 309 return htmlfill.render(
304 310 render('admin/users/user_edit_my_account.html'),
305 311 defaults=errors.value,
306 312 errors=errors.error_dict or {},
307 313 prefix_error=False,
308 314 encoding="UTF-8")
309 315 except Exception:
310 316 log.error(traceback.format_exc())
311 317 h.flash(_('error occurred during update of user %s') \
312 318 % form_result.get('username'), category='error')
313 319
314 320 return redirect(url('my_account'))
315 321
316 322 @NotAnonymous()
317 323 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
318 324 def create_repository(self):
319 325 """GET /_admin/create_repository: Form to create a new item"""
320 326
321 327 c.repo_groups = [('', '')]
322 328 parents_link = lambda k:h.literal('&raquo;'.join(
323 329 map(lambda k:k.group_name,
324 330 k.parents + [k])
325 331 )
326 332 )
327 333
328 334 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
329 335 x in self.sa.query(Group).all()])
330 336 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
331 337
332 338 new_repo = request.GET.get('repo', '')
333 339 c.new_repo = repo_name_slug(new_repo)
334 340
335 341 return render('admin/repos/repo_add_create_repository.html')
336 342
337 343 def get_hg_ui_settings(self):
338 344 ret = self.sa.query(RhodeCodeUi).all()
339 345
340 346 if not ret:
341 347 raise Exception('Could not get application ui settings !')
342 348 settings = {}
343 349 for each in ret:
344 350 k = each.ui_key
345 351 v = each.ui_value
346 352 if k == '/':
347 353 k = 'root_path'
348 354
349 355 if k.find('.') != -1:
350 356 k = k.replace('.', '_')
351 357
352 358 if each.ui_section == 'hooks':
353 359 v = each.ui_active
354 360
355 361 settings[each.ui_section + '_' + k] = v
356 362
357 363 return settings
@@ -1,174 +1,176
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.users
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Users crud controller for pylons
7 7
8 8 :created_on: Apr 4, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29
30 30 from formencode import htmlfill
31 31 from pylons import request, session, tmpl_context as c, url, config
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons.i18n.translation import _
34 34
35 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
35 from rhodecode.lib.exceptions import DefaultUserException, \
36 UserOwnsReposException
36 37 from rhodecode.lib import helpers as h
37 38 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 39 from rhodecode.lib.base import BaseController, render
39 40
40 41 from rhodecode.model.db import User
41 42 from rhodecode.model.forms import UserForm
42 43 from rhodecode.model.user import UserModel
43 44
44 45 log = logging.getLogger(__name__)
45 46
47
46 48 class UsersController(BaseController):
47 49 """REST Controller styled on the Atom Publishing Protocol"""
48 50 # To properly map this controller, ensure your config/routing.py
49 51 # file has a resource setup:
50 52 # map.resource('user', 'users')
51 53
52 54 @LoginRequired()
53 55 @HasPermissionAllDecorator('hg.admin')
54 56 def __before__(self):
55 57 c.admin_user = session.get('admin_user')
56 58 c.admin_username = session.get('admin_username')
57 59 super(UsersController, self).__before__()
58 60 c.available_permissions = config['available_permissions']
59 61
60 62 def index(self, format='html'):
61 63 """GET /users: All items in the collection"""
62 64 # url('users')
63 65
64 66 c.users_list = self.sa.query(User).all()
65 67 return render('admin/users/users.html')
66 68
67 69 def create(self):
68 70 """POST /users: Create a new item"""
69 71 # url('users')
70 72
71 73 user_model = UserModel()
72 74 login_form = UserForm()()
73 75 try:
74 76 form_result = login_form.to_python(dict(request.POST))
75 77 user_model.create(form_result)
76 78 h.flash(_('created user %s') % form_result['username'],
77 79 category='success')
78 80 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
79 81 except formencode.Invalid, errors:
80 82 return htmlfill.render(
81 83 render('admin/users/user_add.html'),
82 84 defaults=errors.value,
83 85 errors=errors.error_dict or {},
84 86 prefix_error=False,
85 87 encoding="UTF-8")
86 88 except Exception:
87 89 log.error(traceback.format_exc())
88 90 h.flash(_('error occurred during creation of user %s') \
89 91 % request.POST.get('username'), category='error')
90 92 return redirect(url('users'))
91 93
92 94 def new(self, format='html'):
93 95 """GET /users/new: Form to create a new item"""
94 96 # url('new_user')
95 97 return render('admin/users/user_add.html')
96 98
97 99 def update(self, id):
98 100 """PUT /users/id: Update an existing item"""
99 101 # Forms posted to this method should contain a hidden field:
100 102 # <input type="hidden" name="_method" value="PUT" />
101 103 # Or using helpers:
102 104 # h.form(url('user', id=ID),
103 105 # method='put')
104 106 # url('user', id=ID)
105 107 user_model = UserModel()
106 108 c.user = user_model.get(id)
107 109
108 110 _form = UserForm(edit=True, old_data={'user_id':id,
109 111 'email':c.user.email})()
110 112 form_result = {}
111 113 try:
112 114 form_result = _form.to_python(dict(request.POST))
113 115 user_model.update(id, form_result)
114 116 h.flash(_('User updated succesfully'), category='success')
115 117
116 118 except formencode.Invalid, errors:
117 119 return htmlfill.render(
118 120 render('admin/users/user_edit.html'),
119 121 defaults=errors.value,
120 122 errors=errors.error_dict or {},
121 123 prefix_error=False,
122 124 encoding="UTF-8")
123 125 except Exception:
124 126 log.error(traceback.format_exc())
125 127 h.flash(_('error occurred during update of user %s') \
126 128 % form_result.get('username'), category='error')
127 129
128 130 return redirect(url('users'))
129 131
130 132 def delete(self, id):
131 133 """DELETE /users/id: Delete an existing item"""
132 134 # Forms posted to this method should contain a hidden field:
133 135 # <input type="hidden" name="_method" value="DELETE" />
134 136 # Or using helpers:
135 137 # h.form(url('user', id=ID),
136 138 # method='delete')
137 139 # url('user', id=ID)
138 140 user_model = UserModel()
139 141 try:
140 142 user_model.delete(id)
141 143 h.flash(_('successfully deleted user'), category='success')
142 144 except (UserOwnsReposException, DefaultUserException), e:
143 145 h.flash(str(e), category='warning')
144 146 except Exception:
145 147 h.flash(_('An error occurred during deletion of user'),
146 148 category='error')
147 149 return redirect(url('users'))
148 150
149 151 def show(self, id, format='html'):
150 152 """GET /users/id: Show a specific item"""
151 153 # url('user', id=ID)
152 154
153
154 155 def edit(self, id, format='html'):
155 156 """GET /users/id/edit: Form to edit an existing item"""
156 157 # url('edit_user', id=ID)
157 158 user_model = UserModel()
158 159 c.user = user_model.get(id)
159 160 if not c.user:
160 161 return redirect(url('users'))
161 162 if c.user.username == 'default':
162 163 h.flash(_("You can't edit this user"), category='warning')
163 164 return redirect(url('users'))
164 165 c.user.permissions = {}
165 c.granted_permissions = user_model.fill_perms(c.user).permissions['global']
166 c.granted_permissions = user_model.fill_perms(c.user)\
167 .permissions['global']
166 168
167 169 defaults = c.user.get_dict()
168 170
169 171 return htmlfill.render(
170 172 render('admin/users/user_edit.html'),
171 173 defaults=defaults,
172 174 encoding="UTF-8",
173 175 force_defaults=False
174 176 )
@@ -1,182 +1,180
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.users_groups
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Users Groups crud controller for pylons
7 7
8 8 :created_on: Jan 25, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28 import formencode
29 29
30 30 from formencode import htmlfill
31 31 from pylons import request, session, tmpl_context as c, url, config
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons.i18n.translation import _
34 34
35 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException
36 35 from rhodecode.lib import helpers as h
37 36 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 37 from rhodecode.lib.base import BaseController, render
39 38
40 39 from rhodecode.model.db import User, UsersGroup
41 40 from rhodecode.model.forms import UserForm, UsersGroupForm
42 41 from rhodecode.model.user import UserModel
43 42 from rhodecode.model.users_group import UsersGroupModel
44 43
45 44 log = logging.getLogger(__name__)
46 45
46
47 47 class UsersGroupsController(BaseController):
48 48 """REST Controller styled on the Atom Publishing Protocol"""
49 49 # To properly map this controller, ensure your config/routing.py
50 50 # file has a resource setup:
51 51 # map.resource('users_group', 'users_groups')
52 52
53 53 @LoginRequired()
54 54 @HasPermissionAllDecorator('hg.admin')
55 55 def __before__(self):
56 56 c.admin_user = session.get('admin_user')
57 57 c.admin_username = session.get('admin_username')
58 58 super(UsersGroupsController, self).__before__()
59 59 c.available_permissions = config['available_permissions']
60 60
61 61 def index(self, format='html'):
62 62 """GET /users_groups: All items in the collection"""
63 63 # url('users_groups')
64 64 c.users_groups_list = self.sa.query(UsersGroup).all()
65 65 return render('admin/users_groups/users_groups.html')
66 66
67 67 def create(self):
68 68 """POST /users_groups: Create a new item"""
69 69 # url('users_groups')
70 70 users_group_model = UsersGroupModel()
71 71 users_group_form = UsersGroupForm()()
72 72 try:
73 73 form_result = users_group_form.to_python(dict(request.POST))
74 74 users_group_model.create(form_result)
75 h.flash(_('created users group %s') % form_result['users_group_name'],
76 category='success')
75 h.flash(_('created users group %s') \
76 % form_result['users_group_name'], category='success')
77 77 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
78 78 except formencode.Invalid, errors:
79 79 return htmlfill.render(
80 80 render('admin/users_groups/users_group_add.html'),
81 81 defaults=errors.value,
82 82 errors=errors.error_dict or {},
83 83 prefix_error=False,
84 84 encoding="UTF-8")
85 85 except Exception:
86 86 log.error(traceback.format_exc())
87 87 h.flash(_('error occurred during creation of users group %s') \
88 88 % request.POST.get('users_group_name'), category='error')
89 89
90 90 return redirect(url('users_groups'))
91 91
92 92 def new(self, format='html'):
93 93 """GET /users_groups/new: Form to create a new item"""
94 94 # url('new_users_group')
95 95 return render('admin/users_groups/users_group_add.html')
96 96
97 97 def update(self, id):
98 98 """PUT /users_groups/id: Update an existing item"""
99 99 # Forms posted to this method should contain a hidden field:
100 100 # <input type="hidden" name="_method" value="PUT" />
101 101 # Or using helpers:
102 102 # h.form(url('users_group', id=ID),
103 103 # method='put')
104 104 # url('users_group', id=ID)
105 105
106
107 106 users_group_model = UsersGroupModel()
108 107 c.users_group = users_group_model.get(id)
109 108 c.group_members = [(x.user_id, x.user.username) for x in
110 109 c.users_group.members]
111 110
112 111 c.available_members = [(x.user_id, x.username) for x in
113 112 self.sa.query(User).all()]
114 113 users_group_form = UsersGroupForm(edit=True,
115 114 old_data=c.users_group.get_dict(),
116 115 available_members=[str(x[0]) for x
117 116 in c.available_members])()
118 117
119 118 try:
120 119 form_result = users_group_form.to_python(request.POST)
121 120 users_group_model.update(id, form_result)
122 h.flash(_('updated users group %s') % form_result['users_group_name'],
121 h.flash(_('updated users group %s') \
122 % form_result['users_group_name'],
123 123 category='success')
124 124 #action_logger(self.rhodecode_user, 'new_user', '', '', self.sa)
125 125 except formencode.Invalid, errors:
126 126 return htmlfill.render(
127 127 render('admin/users_groups/users_group_edit.html'),
128 128 defaults=errors.value,
129 129 errors=errors.error_dict or {},
130 130 prefix_error=False,
131 131 encoding="UTF-8")
132 132 except Exception:
133 133 log.error(traceback.format_exc())
134 134 h.flash(_('error occurred during update of users group %s') \
135 135 % request.POST.get('users_group_name'), category='error')
136 136
137 137 return redirect(url('users_groups'))
138 138
139
140
141 139 def delete(self, id):
142 140 """DELETE /users_groups/id: Delete an existing item"""
143 141 # Forms posted to this method should contain a hidden field:
144 142 # <input type="hidden" name="_method" value="DELETE" />
145 143 # Or using helpers:
146 144 # h.form(url('users_group', id=ID),
147 145 # method='delete')
148 146 # url('users_group', id=ID)
149 147 users_group_model = UsersGroupModel()
150 148 try:
151 149 users_group_model.delete(id)
152 150 h.flash(_('successfully deleted users group'), category='success')
153 151 except Exception:
154 152 h.flash(_('An error occurred during deletion of users group'),
155 153 category='error')
156 154 return redirect(url('users_groups'))
157 155
158 156 def show(self, id, format='html'):
159 157 """GET /users_groups/id: Show a specific item"""
160 158 # url('users_group', id=ID)
161 159
162 160 def edit(self, id, format='html'):
163 161 """GET /users_groups/id/edit: Form to edit an existing item"""
164 162 # url('edit_users_group', id=ID)
165 163
166 164 c.users_group = self.sa.query(UsersGroup).get(id)
167 165 if not c.users_group:
168 166 return redirect(url('users_groups'))
169 167
170 168 c.users_group.permissions = {}
171 169 c.group_members = [(x.user_id, x.user.username) for x in
172 170 c.users_group.members]
173 171 c.available_members = [(x.user_id, x.username) for x in
174 172 self.sa.query(User).all()]
175 173 defaults = c.users_group.get_dict()
176 174
177 175 return htmlfill.render(
178 176 render('admin/users_groups/users_group_edit.html'),
179 177 defaults=defaults,
180 178 encoding="UTF-8",
181 179 force_defaults=False
182 180 )
@@ -1,334 +1,335
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.files
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Files controller for RhodeCode
7 7
8 8 :created_on: Apr 21, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import os
27 27 import logging
28 28 import mimetypes
29 29 import rhodecode.lib.helpers as h
30 30
31 31 from pylons import request, response, session, tmpl_context as c, url
32 32 from pylons.i18n.translation import _
33 33 from pylons.controllers.util import redirect
34 34
35 35 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
36 36 from rhodecode.lib.base import BaseRepoController, render
37 37 from rhodecode.lib.utils import EmptyChangeset
38 38 from rhodecode.model.repo import RepoModel
39 39
40 40 from vcs.backends import ARCHIVE_SPECS
41 41 from vcs.exceptions import RepositoryError, ChangesetDoesNotExistError, \
42 42 EmptyRepositoryError, ImproperArchiveTypeError, VCSError
43 43 from vcs.nodes import FileNode, NodeKind
44 44 from vcs.utils import diffs as differ
45 45
46 46 log = logging.getLogger(__name__)
47 47
48 48
49 49 class FilesController(BaseRepoController):
50 50
51 51 @LoginRequired()
52 52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
53 53 'repository.admin')
54 54 def __before__(self):
55 55 super(FilesController, self).__before__()
56 56 c.cut_off_limit = self.cut_off_limit
57 57
58 58 def __get_cs_or_redirect(self, rev, repo_name):
59 59 """
60 60 Safe way to get changeset if error occur it redirects to tip with
61 61 proper message
62 62
63 63 :param rev: revision to fetch
64 64 :param repo_name: repo name to redirect after
65 65 """
66 66
67 67 try:
68 68 return c.rhodecode_repo.get_changeset(rev)
69 69 except EmptyRepositoryError, e:
70 70 h.flash(_('There are no files yet'), category='warning')
71 71 redirect(h.url('summary_home', repo_name=repo_name))
72 72
73 73 except RepositoryError, e:
74 74 h.flash(str(e), category='warning')
75 75 redirect(h.url('files_home', repo_name=repo_name, revision='tip'))
76 76
77 77 def __get_filenode_or_redirect(self, repo_name, cs, path):
78 78 """
79 79 Returns file_node, if error occurs or given path is directory,
80 80 it'll redirect to top level path
81 81
82 82 :param repo_name: repo_name
83 83 :param cs: given changeset
84 84 :param path: path to lookup
85 85 """
86 86
87 87 try:
88 88 file_node = cs.get_node(path)
89 89 if file_node.is_dir():
90 90 raise RepositoryError('given path is a directory')
91 91 except RepositoryError, e:
92 92 h.flash(str(e), category='warning')
93 93 redirect(h.url('files_home', repo_name=repo_name,
94 94 revision=cs.raw_id))
95 95
96 96 return file_node
97 97
98 98 def index(self, repo_name, revision, f_path):
99 99 #reditect to given revision from form if given
100 100 post_revision = request.POST.get('at_rev', None)
101 101 if post_revision:
102 102 cs = self.__get_cs_or_redirect(post_revision, repo_name)
103 103 redirect(url('files_home', repo_name=c.repo_name,
104 104 revision=cs.raw_id, f_path=f_path))
105 105
106 106 c.changeset = self.__get_cs_or_redirect(revision, repo_name)
107 107 c.branch = request.GET.get('branch', None)
108 108 c.f_path = f_path
109 109
110 110 cur_rev = c.changeset.revision
111 111
112 112 #prev link
113 113 try:
114 114 prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch)
115 115 c.url_prev = url('files_home', repo_name=c.repo_name,
116 116 revision=prev_rev.raw_id, f_path=f_path)
117 117 if c.branch:
118 118 c.url_prev += '?branch=%s' % c.branch
119 119 except (ChangesetDoesNotExistError, VCSError):
120 120 c.url_prev = '#'
121 121
122 122 #next link
123 123 try:
124 124 next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch)
125 125 c.url_next = url('files_home', repo_name=c.repo_name,
126 126 revision=next_rev.raw_id, f_path=f_path)
127 127 if c.branch:
128 128 c.url_next += '?branch=%s' % c.branch
129 129 except (ChangesetDoesNotExistError, VCSError):
130 130 c.url_next = '#'
131 131
132 132 #files or dirs
133 133 try:
134 134 c.files_list = c.changeset.get_node(f_path)
135 135
136 136 if c.files_list.is_file():
137 137 c.file_history = self._get_node_history(c.changeset, f_path)
138 138 else:
139 139 c.file_history = []
140 140 except RepositoryError, e:
141 141 h.flash(str(e), category='warning')
142 142 redirect(h.url('files_home', repo_name=repo_name,
143 143 revision=revision))
144 144
145 145 return render('files/files.html')
146 146
147 147 def rawfile(self, repo_name, revision, f_path):
148 148 cs = self.__get_cs_or_redirect(revision, repo_name)
149 149 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
150 150
151 151 response.content_disposition = 'attachment; filename=%s' % \
152 152 f_path.split(os.sep)[-1].encode('utf8', 'replace')
153 153
154 154 response.content_type = file_node.mimetype
155 155 return file_node.content
156 156
157 157 def raw(self, repo_name, revision, f_path):
158 158 cs = self.__get_cs_or_redirect(revision, repo_name)
159 159 file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path)
160 160
161 161 raw_mimetype_mapping = {
162 162 # map original mimetype to a mimetype used for "show as raw"
163 163 # you can also provide a content-disposition to override the
164 164 # default "attachment" disposition.
165 165 # orig_type: (new_type, new_dispo)
166 166
167 167 # show images inline:
168 168 'image/x-icon': ('image/x-icon', 'inline'),
169 169 'image/png': ('image/png', 'inline'),
170 170 'image/gif': ('image/gif', 'inline'),
171 171 'image/jpeg': ('image/jpeg', 'inline'),
172 172 'image/svg+xml': ('image/svg+xml', 'inline'),
173 173 }
174 174
175 175 mimetype = file_node.mimetype
176 176 try:
177 177 mimetype, dispo = raw_mimetype_mapping[mimetype]
178 178 except KeyError:
179 179 # we don't know anything special about this, handle it safely
180 180 if file_node.is_binary:
181 181 # do same as download raw for binary files
182 182 mimetype, dispo = 'application/octet-stream', 'attachment'
183 183 else:
184 184 # do not just use the original mimetype, but force text/plain,
185 185 # otherwise it would serve text/html and that might be unsafe.
186 186 # Note: underlying vcs library fakes text/plain mimetype if the
187 # mimetype can not be determined and it thinks it is not binary.
188 # This might lead to erroneous text display in some cases, but
189 # helps in other cases, like with text files without extension.
187 # mimetype can not be determined and it thinks it is not
188 # binary.This might lead to erroneous text display in some
189 # cases, but helps in other cases, like with text files
190 # without extension.
190 191 mimetype, dispo = 'text/plain', 'inline'
191 192
192 193 if dispo == 'attachment':
193 194 dispo = 'attachment; filename=%s' % \
194 195 f_path.split(os.sep)[-1].encode('utf8', 'replace')
195 196
196 197 response.content_disposition = dispo
197 198 response.content_type = mimetype
198 199 return file_node.content
199 200
200 201 def annotate(self, repo_name, revision, f_path):
201 202 c.cs = self.__get_cs_or_redirect(revision, repo_name)
202 203 c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path)
203 204
204 205 c.file_history = self._get_node_history(c.cs, f_path)
205 206 c.f_path = f_path
206 207 return render('files/files_annotate.html')
207 208
208 209 def archivefile(self, repo_name, fname):
209 210
210 211 fileformat = None
211 212 revision = None
212 213 ext = None
213 214
214 215 for a_type, ext_data in ARCHIVE_SPECS.items():
215 216 archive_spec = fname.split(ext_data[1])
216 217 if len(archive_spec) == 2 and archive_spec[1] == '':
217 218 fileformat = a_type or ext_data[1]
218 219 revision = archive_spec[0]
219 220 ext = ext_data[1]
220 221
221 222 try:
222 223 dbrepo = RepoModel().get_by_repo_name(repo_name)
223 224 if dbrepo.enable_downloads is False:
224 225 return _('downloads disabled')
225 226
226 227 cs = c.rhodecode_repo.get_changeset(revision)
227 228 content_type = ARCHIVE_SPECS[fileformat][0]
228 229 except ChangesetDoesNotExistError:
229 230 return _('Unknown revision %s') % revision
230 231 except EmptyRepositoryError:
231 232 return _('Empty repository')
232 233 except (ImproperArchiveTypeError, KeyError):
233 234 return _('Unknown archive type')
234 235
235 236 response.content_type = content_type
236 237 response.content_disposition = 'attachment; filename=%s-%s%s' \
237 238 % (repo_name, revision, ext)
238 239
239 240 return cs.get_chunked_archive(stream=None, kind=fileformat)
240 241
241 242 def diff(self, repo_name, f_path):
242 243 diff1 = request.GET.get('diff1')
243 244 diff2 = request.GET.get('diff2')
244 245 c.action = request.GET.get('diff')
245 246 c.no_changes = diff1 == diff2
246 247 c.f_path = f_path
247 248
248 249 try:
249 250 if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
250 251 c.changeset_1 = c.rhodecode_repo.get_changeset(diff1)
251 252 node1 = c.changeset_1.get_node(f_path)
252 253 else:
253 254 c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo)
254 255 node1 = FileNode('.', '', changeset=c.changeset_1)
255 256
256 257 if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
257 258 c.changeset_2 = c.rhodecode_repo.get_changeset(diff2)
258 259 node2 = c.changeset_2.get_node(f_path)
259 260 else:
260 261 c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo)
261 262 node2 = FileNode('.', '', changeset=c.changeset_2)
262 263 except RepositoryError:
263 264 return redirect(url('files_home',
264 265 repo_name=c.repo_name, f_path=f_path))
265 266
266 267 if c.action == 'download':
267 268 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
268 269 format='gitdiff')
269 270
270 271 diff_name = '%s_vs_%s.diff' % (diff1, diff2)
271 272 response.content_type = 'text/plain'
272 273 response.content_disposition = 'attachment; filename=%s' \
273 274 % diff_name
274 275 return diff.raw_diff()
275 276
276 277 elif c.action == 'raw':
277 278 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
278 279 format='gitdiff')
279 280 response.content_type = 'text/plain'
280 281 return diff.raw_diff()
281 282
282 283 elif c.action == 'diff':
283 284
284 285 if node1.is_binary or node2.is_binary:
285 286 c.cur_diff = _('Binary file')
286 287 elif node1.size > self.cut_off_limit or \
287 288 node2.size > self.cut_off_limit:
288 289 c.cur_diff = _('Diff is too big to display')
289 290 else:
290 291 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
291 292 format='gitdiff')
292 293 c.cur_diff = diff.as_html()
293 294 else:
294 295
295 296 #default option
296 297 if node1.is_binary or node2.is_binary:
297 298 c.cur_diff = _('Binary file')
298 299 elif node1.size > self.cut_off_limit or \
299 300 node2.size > self.cut_off_limit:
300 301 c.cur_diff = _('Diff is too big to display')
301 302 else:
302 303 diff = differ.DiffProcessor(differ.get_gitdiff(node1, node2),
303 304 format='gitdiff')
304 305 c.cur_diff = diff.as_html()
305 306
306 307 if not c.cur_diff:
307 308 c.no_changes = True
308 309 return render('files/file_diff.html')
309 310
310 311 def _get_node_history(self, cs, f_path):
311 312 changesets = cs.get_file_history(f_path)
312 313 hist_l = []
313 314
314 315 changesets_group = ([], _("Changesets"))
315 316 branches_group = ([], _("Branches"))
316 317 tags_group = ([], _("Tags"))
317 318
318 319 for chs in changesets:
319 320 n_desc = 'r%s:%s' % (chs.revision, chs.short_id)
320 321 changesets_group[0].append((chs.raw_id, n_desc,))
321 322
322 323 hist_l.append(changesets_group)
323 324
324 325 for name, chs in c.rhodecode_repo.branches.items():
325 326 #chs = chs.split(':')[-1]
326 327 branches_group[0].append((chs, name),)
327 328 hist_l.append(branches_group)
328 329
329 330 for name, chs in c.rhodecode_repo.tags.items():
330 331 #chs = chs.split(':')[-1]
331 332 tags_group[0].append((chs, name),)
332 333 hist_l.append(tags_group)
333 334
334 335 return hist_l
General Comments 0
You need to be logged in to leave comments. Login now