##// END OF EJS Templates
lib: move webhelpers2 and friends to webutils...
Mads Kiilerich -
r8488:67e5b908 default
parent child Browse files
Show More
@@ -32,8 +32,7 b' from tg import tmpl_context as c'
32 from tg.i18n import ugettext as _
32 from tg.i18n import ugettext as _
33 from webob.exc import HTTPFound
33 from webob.exc import HTTPFound
34
34
35 from kallithea.lib import auth_modules
35 from kallithea.lib import auth_modules, webutils
36 from kallithea.lib import helpers as h
37 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
36 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
38 from kallithea.lib.base import BaseController, render
37 from kallithea.lib.base import BaseController, render
39 from kallithea.lib.webutils import url
38 from kallithea.lib.webutils import url
@@ -132,7 +131,7 b' class AuthSettingsController(BaseControl'
132 log.debug("%s = %s", k, str(v))
131 log.debug("%s = %s", k, str(v))
133 setting = db.Setting.create_or_update(k, v)
132 setting = db.Setting.create_or_update(k, v)
134 meta.Session().commit()
133 meta.Session().commit()
135 h.flash(_('Auth settings updated successfully'),
134 webutils.flash(_('Auth settings updated successfully'),
136 category='success')
135 category='success')
137 except formencode.Invalid as errors:
136 except formencode.Invalid as errors:
138 log.error(traceback.format_exc())
137 log.error(traceback.format_exc())
@@ -143,7 +142,7 b' class AuthSettingsController(BaseControl'
143 )
142 )
144 except Exception:
143 except Exception:
145 log.error(traceback.format_exc())
144 log.error(traceback.format_exc())
146 h.flash(_('error occurred during update of auth settings'),
145 webutils.flash(_('error occurred during update of auth settings'),
147 category='error')
146 category='error')
148
147
149 raise HTTPFound(location=url('auth_home'))
148 raise HTTPFound(location=url('auth_home'))
@@ -34,7 +34,7 b' from tg import request'
34 from tg.i18n import ugettext as _
34 from tg.i18n import ugettext as _
35 from webob.exc import HTTPFound
35 from webob.exc import HTTPFound
36
36
37 from kallithea.lib import helpers as h
37 from kallithea.lib import webutils
38 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
38 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
39 from kallithea.lib.base import BaseController, render
39 from kallithea.lib.base import BaseController, render
40 from kallithea.lib.webutils import url
40 from kallithea.lib.webutils import url
@@ -70,7 +70,7 b' class DefaultsController(BaseController)'
70 for k, v in form_result.items():
70 for k, v in form_result.items():
71 setting = db.Setting.create_or_update(k, v)
71 setting = db.Setting.create_or_update(k, v)
72 meta.Session().commit()
72 meta.Session().commit()
73 h.flash(_('Default settings updated successfully'),
73 webutils.flash(_('Default settings updated successfully'),
74 category='success')
74 category='success')
75
75
76 except formencode.Invalid as errors:
76 except formencode.Invalid as errors:
@@ -85,7 +85,7 b' class DefaultsController(BaseController)'
85 force_defaults=False)
85 force_defaults=False)
86 except Exception:
86 except Exception:
87 log.error(traceback.format_exc())
87 log.error(traceback.format_exc())
88 h.flash(_('Error occurred during update of defaults'),
88 webutils.flash(_('Error occurred during update of defaults'),
89 category='error')
89 category='error')
90
90
91 raise HTTPFound(location=url('defaults'))
91 raise HTTPFound(location=url('defaults'))
@@ -35,8 +35,7 b' from tg import tmpl_context as c'
35 from tg.i18n import ugettext as _
35 from tg.i18n import ugettext as _
36 from webob.exc import HTTPForbidden, HTTPFound, HTTPNotFound
36 from webob.exc import HTTPForbidden, HTTPFound, HTTPNotFound
37
37
38 from kallithea.lib import auth
38 from kallithea.lib import auth, webutils
39 from kallithea.lib import helpers as h
40 from kallithea.lib.auth import LoginRequired
39 from kallithea.lib.auth import LoginRequired
41 from kallithea.lib.base import BaseController, jsonify, render
40 from kallithea.lib.base import BaseController, jsonify, render
42 from kallithea.lib.page import Page
41 from kallithea.lib.page import Page
@@ -144,7 +143,7 b' class GistsController(BaseController):'
144
143
145 except Exception as e:
144 except Exception as e:
146 log.error(traceback.format_exc())
145 log.error(traceback.format_exc())
147 h.flash(_('Error occurred during gist creation'), category='error')
146 webutils.flash(_('Error occurred during gist creation'), category='error')
148 raise HTTPFound(location=url('new_gist'))
147 raise HTTPFound(location=url('new_gist'))
149 raise HTTPFound(location=url('gist', gist_id=new_gist_id))
148 raise HTTPFound(location=url('gist', gist_id=new_gist_id))
150
149
@@ -160,7 +159,7 b' class GistsController(BaseController):'
160 if auth.HasPermissionAny('hg.admin')() or owner:
159 if auth.HasPermissionAny('hg.admin')() or owner:
161 GistModel().delete(gist)
160 GistModel().delete(gist)
162 meta.Session().commit()
161 meta.Session().commit()
163 h.flash(_('Deleted gist %s') % gist.gist_access_id, category='success')
162 webutils.flash(_('Deleted gist %s') % gist.gist_access_id, category='success')
164 else:
163 else:
165 raise HTTPForbidden()
164 raise HTTPForbidden()
166
165
@@ -233,15 +232,15 b' class GistsController(BaseController):'
233 )
232 )
234
233
235 meta.Session().commit()
234 meta.Session().commit()
236 h.flash(_('Successfully updated gist content'), category='success')
235 webutils.flash(_('Successfully updated gist content'), category='success')
237 except NodeNotChangedError:
236 except NodeNotChangedError:
238 # raised if nothing was changed in repo itself. We anyway then
237 # raised if nothing was changed in repo itself. We anyway then
239 # store only DB stuff for gist
238 # store only DB stuff for gist
240 meta.Session().commit()
239 meta.Session().commit()
241 h.flash(_('Successfully updated gist data'), category='success')
240 webutils.flash(_('Successfully updated gist data'), category='success')
242 except Exception:
241 except Exception:
243 log.error(traceback.format_exc())
242 log.error(traceback.format_exc())
244 h.flash(_('Error occurred during update of gist %s') % gist_id,
243 webutils.flash(_('Error occurred during update of gist %s') % gist_id,
245 category='error')
244 category='error')
246
245
247 raise HTTPFound(location=url('gist', gist_id=gist_id))
246 raise HTTPFound(location=url('gist', gist_id=gist_id))
@@ -35,8 +35,7 b' from tg import tmpl_context as c'
35 from tg.i18n import ugettext as _
35 from tg.i18n import ugettext as _
36 from webob.exc import HTTPFound
36 from webob.exc import HTTPFound
37
37
38 from kallithea.lib import auth_modules
38 from kallithea.lib import auth_modules, webutils
39 from kallithea.lib import helpers as h
40 from kallithea.lib.auth import AuthUser, LoginRequired
39 from kallithea.lib.auth import AuthUser, LoginRequired
41 from kallithea.lib.base import BaseController, IfSshEnabled, render
40 from kallithea.lib.base import BaseController, IfSshEnabled, render
42 from kallithea.lib.utils2 import generate_api_key, safe_int
41 from kallithea.lib.utils2 import generate_api_key, safe_int
@@ -61,7 +60,7 b' class MyAccountController(BaseController'
61 def __load_data(self):
60 def __load_data(self):
62 c.user = db.User.get(request.authuser.user_id)
61 c.user = db.User.get(request.authuser.user_id)
63 if c.user.is_default_user:
62 if c.user.is_default_user:
64 h.flash(_("You can't edit this user since it's"
63 webutils.flash(_("You can't edit this user since it's"
65 " crucial for entire application"), category='warning')
64 " crucial for entire application"), category='warning')
66 raise HTTPFound(location=url('users'))
65 raise HTTPFound(location=url('users'))
67
66
@@ -110,7 +109,7 b' class MyAccountController(BaseController'
110
109
111 UserModel().update(request.authuser.user_id, form_result,
110 UserModel().update(request.authuser.user_id, form_result,
112 skip_attrs=skip_attrs)
111 skip_attrs=skip_attrs)
113 h.flash(_('Your account was updated successfully'),
112 webutils.flash(_('Your account was updated successfully'),
114 category='success')
113 category='success')
115 meta.Session().commit()
114 meta.Session().commit()
116 update = True
115 update = True
@@ -125,7 +124,7 b' class MyAccountController(BaseController'
125 force_defaults=False)
124 force_defaults=False)
126 except Exception:
125 except Exception:
127 log.error(traceback.format_exc())
126 log.error(traceback.format_exc())
128 h.flash(_('Error occurred during update of user %s')
127 webutils.flash(_('Error occurred during update of user %s')
129 % form_result.get('username'), category='error')
128 % form_result.get('username'), category='error')
130 if update:
129 if update:
131 raise HTTPFound(location='my_account')
130 raise HTTPFound(location='my_account')
@@ -148,7 +147,7 b' class MyAccountController(BaseController'
148 form_result = _form.to_python(request.POST)
147 form_result = _form.to_python(request.POST)
149 UserModel().update(request.authuser.user_id, form_result)
148 UserModel().update(request.authuser.user_id, form_result)
150 meta.Session().commit()
149 meta.Session().commit()
151 h.flash(_("Successfully updated password"), category='success')
150 webutils.flash(_("Successfully updated password"), category='success')
152 except formencode.Invalid as errors:
151 except formencode.Invalid as errors:
153 return htmlfill.render(
152 return htmlfill.render(
154 render('admin/my_account/my_account.html'),
153 render('admin/my_account/my_account.html'),
@@ -159,7 +158,7 b' class MyAccountController(BaseController'
159 force_defaults=False)
158 force_defaults=False)
160 except Exception:
159 except Exception:
161 log.error(traceback.format_exc())
160 log.error(traceback.format_exc())
162 h.flash(_('Error occurred during update of user password'),
161 webutils.flash(_('Error occurred during update of user password'),
163 category='error')
162 category='error')
164 return render('admin/my_account/my_account.html')
163 return render('admin/my_account/my_account.html')
165
164
@@ -200,13 +199,13 b' class MyAccountController(BaseController'
200 try:
199 try:
201 UserModel().add_extra_email(request.authuser.user_id, email)
200 UserModel().add_extra_email(request.authuser.user_id, email)
202 meta.Session().commit()
201 meta.Session().commit()
203 h.flash(_("Added email %s to user") % email, category='success')
202 webutils.flash(_("Added email %s to user") % email, category='success')
204 except formencode.Invalid as error:
203 except formencode.Invalid as error:
205 msg = error.error_dict['email']
204 msg = error.error_dict['email']
206 h.flash(msg, category='error')
205 webutils.flash(msg, category='error')
207 except Exception:
206 except Exception:
208 log.error(traceback.format_exc())
207 log.error(traceback.format_exc())
209 h.flash(_('An error occurred during email saving'),
208 webutils.flash(_('An error occurred during email saving'),
210 category='error')
209 category='error')
211 raise HTTPFound(location=url('my_account_emails'))
210 raise HTTPFound(location=url('my_account_emails'))
212
211
@@ -215,7 +214,7 b' class MyAccountController(BaseController'
215 user_model = UserModel()
214 user_model = UserModel()
216 user_model.delete_extra_email(request.authuser.user_id, email_id)
215 user_model.delete_extra_email(request.authuser.user_id, email_id)
217 meta.Session().commit()
216 meta.Session().commit()
218 h.flash(_("Removed email from user"), category='success')
217 webutils.flash(_("Removed email from user"), category='success')
219 raise HTTPFound(location=url('my_account_emails'))
218 raise HTTPFound(location=url('my_account_emails'))
220
219
221 def my_account_api_keys(self):
220 def my_account_api_keys(self):
@@ -239,7 +238,7 b' class MyAccountController(BaseController'
239 description = request.POST.get('description')
238 description = request.POST.get('description')
240 ApiKeyModel().create(request.authuser.user_id, description, lifetime)
239 ApiKeyModel().create(request.authuser.user_id, description, lifetime)
241 meta.Session().commit()
240 meta.Session().commit()
242 h.flash(_("API key successfully created"), category='success')
241 webutils.flash(_("API key successfully created"), category='success')
243 raise HTTPFound(location=url('my_account_api_keys'))
242 raise HTTPFound(location=url('my_account_api_keys'))
244
243
245 def my_account_api_keys_delete(self):
244 def my_account_api_keys_delete(self):
@@ -248,11 +247,11 b' class MyAccountController(BaseController'
248 user = db.User.get(request.authuser.user_id)
247 user = db.User.get(request.authuser.user_id)
249 user.api_key = generate_api_key()
248 user.api_key = generate_api_key()
250 meta.Session().commit()
249 meta.Session().commit()
251 h.flash(_("API key successfully reset"), category='success')
250 webutils.flash(_("API key successfully reset"), category='success')
252 elif api_key:
251 elif api_key:
253 ApiKeyModel().delete(api_key, request.authuser.user_id)
252 ApiKeyModel().delete(api_key, request.authuser.user_id)
254 meta.Session().commit()
253 meta.Session().commit()
255 h.flash(_("API key successfully deleted"), category='success')
254 webutils.flash(_("API key successfully deleted"), category='success')
256
255
257 raise HTTPFound(location=url('my_account_api_keys'))
256 raise HTTPFound(location=url('my_account_api_keys'))
258
257
@@ -272,9 +271,9 b' class MyAccountController(BaseController'
272 description, public_key)
271 description, public_key)
273 meta.Session().commit()
272 meta.Session().commit()
274 SshKeyModel().write_authorized_keys()
273 SshKeyModel().write_authorized_keys()
275 h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
274 webutils.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
276 except SshKeyModelException as e:
275 except SshKeyModelException as e:
277 h.flash(e.args[0], category='error')
276 webutils.flash(e.args[0], category='error')
278 raise HTTPFound(location=url('my_account_ssh_keys'))
277 raise HTTPFound(location=url('my_account_ssh_keys'))
279
278
280 @IfSshEnabled
279 @IfSshEnabled
@@ -284,7 +283,7 b' class MyAccountController(BaseController'
284 SshKeyModel().delete(fingerprint, request.authuser.user_id)
283 SshKeyModel().delete(fingerprint, request.authuser.user_id)
285 meta.Session().commit()
284 meta.Session().commit()
286 SshKeyModel().write_authorized_keys()
285 SshKeyModel().write_authorized_keys()
287 h.flash(_("SSH key successfully deleted"), category='success')
286 webutils.flash(_("SSH key successfully deleted"), category='success')
288 except SshKeyModelException as e:
287 except SshKeyModelException as e:
289 h.flash(e.args[0], category='error')
288 webutils.flash(e.args[0], category='error')
290 raise HTTPFound(location=url('my_account_ssh_keys'))
289 raise HTTPFound(location=url('my_account_ssh_keys'))
@@ -36,7 +36,7 b' from tg import tmpl_context as c'
36 from tg.i18n import ugettext as _
36 from tg.i18n import ugettext as _
37 from webob.exc import HTTPFound
37 from webob.exc import HTTPFound
38
38
39 from kallithea.lib import helpers as h
39 from kallithea.lib import webutils
40 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
40 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
41 from kallithea.lib.base import BaseController, render
41 from kallithea.lib.base import BaseController, render
42 from kallithea.lib.webutils import url
42 from kallithea.lib.webutils import url
@@ -113,7 +113,7 b' class PermissionsController(BaseControll'
113 form_result.update({'perm_user_name': 'default'})
113 form_result.update({'perm_user_name': 'default'})
114 PermissionModel().update(form_result)
114 PermissionModel().update(form_result)
115 meta.Session().commit()
115 meta.Session().commit()
116 h.flash(_('Global permissions updated successfully'),
116 webutils.flash(_('Global permissions updated successfully'),
117 category='success')
117 category='success')
118
118
119 except formencode.Invalid as errors:
119 except formencode.Invalid as errors:
@@ -128,7 +128,7 b' class PermissionsController(BaseControll'
128 force_defaults=False)
128 force_defaults=False)
129 except Exception:
129 except Exception:
130 log.error(traceback.format_exc())
130 log.error(traceback.format_exc())
131 h.flash(_('Error occurred during update of permissions'),
131 webutils.flash(_('Error occurred during update of permissions'),
132 category='error')
132 category='error')
133
133
134 raise HTTPFound(location=url('admin_permissions'))
134 raise HTTPFound(location=url('admin_permissions'))
@@ -37,6 +37,7 b' from tg.i18n import ungettext'
37 from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound
37 from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound
38
38
39 from kallithea.lib import helpers as h
39 from kallithea.lib import helpers as h
40 from kallithea.lib import webutils
40 from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoGroupPermissionLevelDecorator, LoginRequired
41 from kallithea.lib.auth import HasPermissionAny, HasRepoGroupPermissionLevel, HasRepoGroupPermissionLevelDecorator, LoginRequired
41 from kallithea.lib.base import BaseController, render
42 from kallithea.lib.base import BaseController, render
42 from kallithea.lib.utils2 import safe_int
43 from kallithea.lib.utils2 import safe_int
@@ -118,7 +119,7 b' class RepoGroupsController(BaseControlle'
118 repo_groups_data.append({
119 repo_groups_data.append({
119 "raw_name": repo_gr.group_name,
120 "raw_name": repo_gr.group_name,
120 "group_name": repo_group_name(repo_gr.group_name, children_groups),
121 "group_name": repo_group_name(repo_gr.group_name, children_groups),
121 "desc": h.escape(repo_gr.group_description),
122 "desc": webutils.escape(repo_gr.group_description),
122 "repos": repo_count,
123 "repos": repo_count,
123 "owner": h.person(repo_gr.owner),
124 "owner": h.person(repo_gr.owner),
124 "action": repo_group_actions(repo_gr.group_id, repo_gr.group_name,
125 "action": repo_group_actions(repo_gr.group_id, repo_gr.group_name,
@@ -161,14 +162,14 b' class RepoGroupsController(BaseControlle'
161 force_defaults=False)
162 force_defaults=False)
162 except Exception:
163 except Exception:
163 log.error(traceback.format_exc())
164 log.error(traceback.format_exc())
164 h.flash(_('Error occurred during creation of repository group %s')
165 webutils.flash(_('Error occurred during creation of repository group %s')
165 % request.POST.get('group_name'), category='error')
166 % request.POST.get('group_name'), category='error')
166 if form_result is None:
167 if form_result is None:
167 raise
168 raise
168 parent_group_id = form_result['parent_group_id']
169 parent_group_id = form_result['parent_group_id']
169 # TODO: maybe we should get back to the main view, not the admin one
170 # TODO: maybe we should get back to the main view, not the admin one
170 raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id))
171 raise HTTPFound(location=url('repos_groups', parent_group=parent_group_id))
171 h.flash(_('Created repository group %s') % gr.group_name,
172 webutils.flash(_('Created repository group %s') % gr.group_name,
172 category='success')
173 category='success')
173 raise HTTPFound(location=url('repos_group_home', group_name=gr.group_name))
174 raise HTTPFound(location=url('repos_group_home', group_name=gr.group_name))
174
175
@@ -215,7 +216,7 b' class RepoGroupsController(BaseControlle'
215
216
216 new_gr = RepoGroupModel().update(group_name, form_result)
217 new_gr = RepoGroupModel().update(group_name, form_result)
217 meta.Session().commit()
218 meta.Session().commit()
218 h.flash(_('Updated repository group %s')
219 webutils.flash(_('Updated repository group %s')
219 % form_result['group_name'], category='success')
220 % form_result['group_name'], category='success')
220 # we now have new name !
221 # we now have new name !
221 group_name = new_gr.group_name
222 group_name = new_gr.group_name
@@ -231,7 +232,7 b' class RepoGroupsController(BaseControlle'
231 force_defaults=False)
232 force_defaults=False)
232 except Exception:
233 except Exception:
233 log.error(traceback.format_exc())
234 log.error(traceback.format_exc())
234 h.flash(_('Error occurred during update of repository group %s')
235 webutils.flash(_('Error occurred during update of repository group %s')
235 % request.POST.get('group_name'), category='error')
236 % request.POST.get('group_name'), category='error')
236
237
237 raise HTTPFound(location=url('edit_repo_group', group_name=group_name))
238 raise HTTPFound(location=url('edit_repo_group', group_name=group_name))
@@ -241,25 +242,25 b' class RepoGroupsController(BaseControlle'
241 gr = c.repo_group = db.RepoGroup.guess_instance(group_name)
242 gr = c.repo_group = db.RepoGroup.guess_instance(group_name)
242 repos = gr.repositories.all()
243 repos = gr.repositories.all()
243 if repos:
244 if repos:
244 h.flash(_('This group contains %s repositories and cannot be '
245 webutils.flash(_('This group contains %s repositories and cannot be '
245 'deleted') % len(repos), category='warning')
246 'deleted') % len(repos), category='warning')
246 raise HTTPFound(location=url('repos_groups'))
247 raise HTTPFound(location=url('repos_groups'))
247
248
248 children = gr.children.all()
249 children = gr.children.all()
249 if children:
250 if children:
250 h.flash(_('This group contains %s subgroups and cannot be deleted'
251 webutils.flash(_('This group contains %s subgroups and cannot be deleted'
251 % (len(children))), category='warning')
252 % (len(children))), category='warning')
252 raise HTTPFound(location=url('repos_groups'))
253 raise HTTPFound(location=url('repos_groups'))
253
254
254 try:
255 try:
255 RepoGroupModel().delete(group_name)
256 RepoGroupModel().delete(group_name)
256 meta.Session().commit()
257 meta.Session().commit()
257 h.flash(_('Removed repository group %s') % group_name,
258 webutils.flash(_('Removed repository group %s') % group_name,
258 category='success')
259 category='success')
259 # TODO: in future action_logger(, '', '', '')
260 # TODO: in future action_logger(, '', '', '')
260 except Exception:
261 except Exception:
261 log.error(traceback.format_exc())
262 log.error(traceback.format_exc())
262 h.flash(_('Error occurred during deletion of repository group %s')
263 webutils.flash(_('Error occurred during deletion of repository group %s')
263 % group_name, category='error')
264 % group_name, category='error')
264
265
265 if gr.parent_group:
266 if gr.parent_group:
@@ -344,7 +345,7 b' class RepoGroupsController(BaseControlle'
344 if not request.authuser.is_admin:
345 if not request.authuser.is_admin:
345 if self._revoke_perms_on_yourself(form_result):
346 if self._revoke_perms_on_yourself(form_result):
346 msg = _('Cannot revoke permission for yourself as admin')
347 msg = _('Cannot revoke permission for yourself as admin')
347 h.flash(msg, category='warning')
348 webutils.flash(msg, category='warning')
348 raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
349 raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
349 recursive = form_result['recursive']
350 recursive = form_result['recursive']
350 # iterate over all members(if in recursive mode) of this groups and
351 # iterate over all members(if in recursive mode) of this groups and
@@ -358,7 +359,7 b' class RepoGroupsController(BaseControlle'
358 #action_logger(request.authuser, 'admin_changed_repo_permissions',
359 #action_logger(request.authuser, 'admin_changed_repo_permissions',
359 # repo_name, request.ip_addr)
360 # repo_name, request.ip_addr)
360 meta.Session().commit()
361 meta.Session().commit()
361 h.flash(_('Repository group permissions updated'), category='success')
362 webutils.flash(_('Repository group permissions updated'), category='success')
362 raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
363 raise HTTPFound(location=url('edit_repo_group_perms', group_name=group_name))
363
364
364 @HasRepoGroupPermissionLevelDecorator('admin')
365 @HasRepoGroupPermissionLevelDecorator('admin')
@@ -374,7 +375,7 b' class RepoGroupsController(BaseControlle'
374 if not request.authuser.is_admin:
375 if not request.authuser.is_admin:
375 if obj_type == 'user' and request.authuser.user_id == obj_id:
376 if obj_type == 'user' and request.authuser.user_id == obj_id:
376 msg = _('Cannot revoke permission for yourself as admin')
377 msg = _('Cannot revoke permission for yourself as admin')
377 h.flash(msg, category='warning')
378 webutils.flash(msg, category='warning')
378 raise Exception('revoke admin permission on self')
379 raise Exception('revoke admin permission on self')
379 recursive = request.POST.get('recursive', 'none')
380 recursive = request.POST.get('recursive', 'none')
380 if obj_type == 'user':
381 if obj_type == 'user':
@@ -390,6 +391,6 b' class RepoGroupsController(BaseControlle'
390 meta.Session().commit()
391 meta.Session().commit()
391 except Exception:
392 except Exception:
392 log.error(traceback.format_exc())
393 log.error(traceback.format_exc())
393 h.flash(_('An error occurred during revoking of permission'),
394 webutils.flash(_('An error occurred during revoking of permission'),
394 category='error')
395 category='error')
395 raise HTTPInternalServerError()
396 raise HTTPInternalServerError()
@@ -37,7 +37,6 b' from tg.i18n import ugettext as _'
37 from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound
37 from webob.exc import HTTPForbidden, HTTPFound, HTTPInternalServerError, HTTPNotFound
38
38
39 import kallithea
39 import kallithea
40 from kallithea.lib import helpers as h
41 from kallithea.lib import webutils
40 from kallithea.lib import webutils
42 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired, NotAnonymous
41 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired, NotAnonymous
43 from kallithea.lib.base import BaseRepoController, jsonify, render
42 from kallithea.lib.base import BaseRepoController, jsonify, render
@@ -125,7 +124,7 b' class ReposController(BaseRepoController'
125 log.error(traceback.format_exc())
124 log.error(traceback.format_exc())
126 msg = (_('Error creating repository %s')
125 msg = (_('Error creating repository %s')
127 % form_result.get('repo_name'))
126 % form_result.get('repo_name'))
128 h.flash(msg, category='error')
127 webutils.flash(msg, category='error')
129 raise HTTPFound(location=url('home'))
128 raise HTTPFound(location=url('home'))
130
129
131 raise HTTPFound(location=webutils.url('repo_creating_home',
130 raise HTTPFound(location=webutils.url('repo_creating_home',
@@ -179,19 +178,19 b' class ReposController(BaseRepoController'
179 repo = db.Repository.get_by_repo_name(repo_name)
178 repo = db.Repository.get_by_repo_name(repo_name)
180 if repo and repo.repo_state == db.Repository.STATE_CREATED:
179 if repo and repo.repo_state == db.Repository.STATE_CREATED:
181 if repo.clone_uri:
180 if repo.clone_uri:
182 h.flash(_('Created repository %s from %s')
181 webutils.flash(_('Created repository %s from %s')
183 % (repo.repo_name, repo.clone_uri_hidden), category='success')
182 % (repo.repo_name, repo.clone_uri_hidden), category='success')
184 else:
183 else:
185 repo_url = h.link_to(repo.repo_name,
184 repo_url = webutils.link_to(repo.repo_name,
186 webutils.url('summary_home',
185 webutils.url('summary_home',
187 repo_name=repo.repo_name))
186 repo_name=repo.repo_name))
188 fork = repo.fork
187 fork = repo.fork
189 if fork is not None:
188 if fork is not None:
190 fork_name = fork.repo_name
189 fork_name = fork.repo_name
191 h.flash(h.HTML(_('Forked repository %s as %s'))
190 webutils.flash(webutils.HTML(_('Forked repository %s as %s'))
192 % (fork_name, repo_url), category='success')
191 % (fork_name, repo_url), category='success')
193 else:
192 else:
194 h.flash(h.HTML(_('Created repository %s')) % repo_url,
193 webutils.flash(webutils.HTML(_('Created repository %s')) % repo_url,
195 category='success')
194 category='success')
196 return {'result': True}
195 return {'result': True}
197 return {'result': False}
196 return {'result': False}
@@ -220,7 +219,7 b' class ReposController(BaseRepoController'
220 form_result = _form.to_python(dict(request.POST))
219 form_result = _form.to_python(dict(request.POST))
221 repo = repo_model.update(repo_name, **form_result)
220 repo = repo_model.update(repo_name, **form_result)
222 ScmModel().mark_for_invalidation(repo_name)
221 ScmModel().mark_for_invalidation(repo_name)
223 h.flash(_('Repository %s updated successfully') % repo_name,
222 webutils.flash(_('Repository %s updated successfully') % repo_name,
224 category='success')
223 category='success')
225 changed_name = repo.repo_name
224 changed_name = repo.repo_name
226 action_logger(request.authuser, 'admin_updated_repo',
225 action_logger(request.authuser, 'admin_updated_repo',
@@ -240,7 +239,7 b' class ReposController(BaseRepoController'
240
239
241 except Exception:
240 except Exception:
242 log.error(traceback.format_exc())
241 log.error(traceback.format_exc())
243 h.flash(_('Error occurred during update of repository %s')
242 webutils.flash(_('Error occurred during update of repository %s')
244 % repo_name, category='error')
243 % repo_name, category='error')
245 raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
244 raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
246
245
@@ -257,23 +256,23 b' class ReposController(BaseRepoController'
257 do = request.POST['forks']
256 do = request.POST['forks']
258 if do == 'detach_forks':
257 if do == 'detach_forks':
259 handle_forks = 'detach'
258 handle_forks = 'detach'
260 h.flash(_('Detached %s forks') % _forks, category='success')
259 webutils.flash(_('Detached %s forks') % _forks, category='success')
261 elif do == 'delete_forks':
260 elif do == 'delete_forks':
262 handle_forks = 'delete'
261 handle_forks = 'delete'
263 h.flash(_('Deleted %s forks') % _forks, category='success')
262 webutils.flash(_('Deleted %s forks') % _forks, category='success')
264 repo_model.delete(repo, forks=handle_forks)
263 repo_model.delete(repo, forks=handle_forks)
265 action_logger(request.authuser, 'admin_deleted_repo',
264 action_logger(request.authuser, 'admin_deleted_repo',
266 repo_name, request.ip_addr)
265 repo_name, request.ip_addr)
267 ScmModel().mark_for_invalidation(repo_name)
266 ScmModel().mark_for_invalidation(repo_name)
268 h.flash(_('Deleted repository %s') % repo_name, category='success')
267 webutils.flash(_('Deleted repository %s') % repo_name, category='success')
269 meta.Session().commit()
268 meta.Session().commit()
270 except AttachedForksError:
269 except AttachedForksError:
271 h.flash(_('Cannot delete repository %s which still has forks')
270 webutils.flash(_('Cannot delete repository %s which still has forks')
272 % repo_name, category='warning')
271 % repo_name, category='warning')
273
272
274 except Exception:
273 except Exception:
275 log.error(traceback.format_exc())
274 log.error(traceback.format_exc())
276 h.flash(_('An error occurred during deletion of %s') % repo_name,
275 webutils.flash(_('An error occurred during deletion of %s') % repo_name,
277 category='error')
276 category='error')
278
277
279 if repo.group:
278 if repo.group:
@@ -313,7 +312,7 b' class ReposController(BaseRepoController'
313 #action_logger(request.authuser, 'admin_changed_repo_permissions',
312 #action_logger(request.authuser, 'admin_changed_repo_permissions',
314 # repo_name, request.ip_addr)
313 # repo_name, request.ip_addr)
315 meta.Session().commit()
314 meta.Session().commit()
316 h.flash(_('Repository permissions updated'), category='success')
315 webutils.flash(_('Repository permissions updated'), category='success')
317 raise HTTPFound(location=url('edit_repo_perms', repo_name=repo_name))
316 raise HTTPFound(location=url('edit_repo_perms', repo_name=repo_name))
318
317
319 @HasRepoPermissionLevelDecorator('admin')
318 @HasRepoPermissionLevelDecorator('admin')
@@ -342,7 +341,7 b' class ReposController(BaseRepoController'
342 meta.Session().commit()
341 meta.Session().commit()
343 except Exception:
342 except Exception:
344 log.error(traceback.format_exc())
343 log.error(traceback.format_exc())
345 h.flash(_('An error occurred during revoking of permission'),
344 webutils.flash(_('An error occurred during revoking of permission'),
346 category='error')
345 category='error')
347 raise HTTPInternalServerError()
346 raise HTTPInternalServerError()
348 return []
347 return []
@@ -372,10 +371,10 b' class ReposController(BaseRepoController'
372 meta.Session().add(new_field)
371 meta.Session().add(new_field)
373 meta.Session().commit()
372 meta.Session().commit()
374 except formencode.Invalid as e:
373 except formencode.Invalid as e:
375 h.flash(_('Field validation error: %s') % e.msg, category='error')
374 webutils.flash(_('Field validation error: %s') % e.msg, category='error')
376 except Exception as e:
375 except Exception as e:
377 log.error(traceback.format_exc())
376 log.error(traceback.format_exc())
378 h.flash(_('An error occurred during creation of field: %r') % e, category='error')
377 webutils.flash(_('An error occurred during creation of field: %r') % e, category='error')
379 raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
378 raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
380
379
381 @HasRepoPermissionLevelDecorator('admin')
380 @HasRepoPermissionLevelDecorator('admin')
@@ -387,7 +386,7 b' class ReposController(BaseRepoController'
387 except Exception as e:
386 except Exception as e:
388 log.error(traceback.format_exc())
387 log.error(traceback.format_exc())
389 msg = _('An error occurred during removal of field')
388 msg = _('An error occurred during removal of field')
390 h.flash(msg, category='error')
389 webutils.flash(msg, category='error')
391 raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
390 raise HTTPFound(location=url('edit_repo_fields', repo_name=repo_name))
392
391
393 @HasRepoPermissionLevelDecorator('admin')
392 @HasRepoPermissionLevelDecorator('admin')
@@ -432,11 +431,11 b' class ReposController(BaseRepoController'
432 repo_id = db.Repository.get_by_repo_name(repo_name).repo_id
431 repo_id = db.Repository.get_by_repo_name(repo_name).repo_id
433 user_id = kallithea.DEFAULT_USER_ID
432 user_id = kallithea.DEFAULT_USER_ID
434 self.scm_model.toggle_following_repo(repo_id, user_id)
433 self.scm_model.toggle_following_repo(repo_id, user_id)
435 h.flash(_('Updated repository visibility in public journal'),
434 webutils.flash(_('Updated repository visibility in public journal'),
436 category='success')
435 category='success')
437 meta.Session().commit()
436 meta.Session().commit()
438 except Exception:
437 except Exception:
439 h.flash(_('An error occurred during setting this'
438 webutils.flash(_('An error occurred during setting this'
440 ' repository in public journal'),
439 ' repository in public journal'),
441 category='error')
440 category='error')
442 raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
441 raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
@@ -454,14 +453,14 b' class ReposController(BaseRepoController'
454 request.authuser.username)
453 request.authuser.username)
455 fork = repo.fork.repo_name if repo.fork else _('Nothing')
454 fork = repo.fork.repo_name if repo.fork else _('Nothing')
456 meta.Session().commit()
455 meta.Session().commit()
457 h.flash(_('Marked repository %s as fork of %s') % (repo_name, fork),
456 webutils.flash(_('Marked repository %s as fork of %s') % (repo_name, fork),
458 category='success')
457 category='success')
459 except RepositoryError as e:
458 except RepositoryError as e:
460 log.error(traceback.format_exc())
459 log.error(traceback.format_exc())
461 h.flash(e, category='error')
460 webutils.flash(e, category='error')
462 except Exception as e:
461 except Exception as e:
463 log.error(traceback.format_exc())
462 log.error(traceback.format_exc())
464 h.flash(_('An error occurred during this operation'),
463 webutils.flash(_('An error occurred during this operation'),
465 category='error')
464 category='error')
466
465
467 raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
466 raise HTTPFound(location=url('edit_repo_advanced', repo_name=repo_name))
@@ -473,10 +472,10 b' class ReposController(BaseRepoController'
473 if request.POST:
472 if request.POST:
474 try:
473 try:
475 ScmModel().pull_changes(repo_name, request.authuser.username, request.ip_addr)
474 ScmModel().pull_changes(repo_name, request.authuser.username, request.ip_addr)
476 h.flash(_('Pulled from remote location'), category='success')
475 webutils.flash(_('Pulled from remote location'), category='success')
477 except Exception as e:
476 except Exception as e:
478 log.error(traceback.format_exc())
477 log.error(traceback.format_exc())
479 h.flash(_('An error occurred during pull from remote location'),
478 webutils.flash(_('An error occurred during pull from remote location'),
480 category='error')
479 category='error')
481 raise HTTPFound(location=url('edit_repo_remote', repo_name=c.repo_name))
480 raise HTTPFound(location=url('edit_repo_remote', repo_name=c.repo_name))
482 return render('admin/repos/repo_edit.html')
481 return render('admin/repos/repo_edit.html')
@@ -507,7 +506,7 b' class ReposController(BaseRepoController'
507 meta.Session().commit()
506 meta.Session().commit()
508 except Exception as e:
507 except Exception as e:
509 log.error(traceback.format_exc())
508 log.error(traceback.format_exc())
510 h.flash(_('An error occurred during deletion of repository stats'),
509 webutils.flash(_('An error occurred during deletion of repository stats'),
511 category='error')
510 category='error')
512 raise HTTPFound(location=url('edit_repo_statistics', repo_name=c.repo_name))
511 raise HTTPFound(location=url('edit_repo_statistics', repo_name=c.repo_name))
513
512
@@ -35,7 +35,6 b' from tg import tmpl_context as c'
35 from tg.i18n import ugettext as _
35 from tg.i18n import ugettext as _
36 from webob.exc import HTTPFound
36 from webob.exc import HTTPFound
37
37
38 from kallithea.lib import helpers as h
39 from kallithea.lib import webutils
38 from kallithea.lib import webutils
40 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
39 from kallithea.lib.auth import HasPermissionAnyDecorator, LoginRequired
41 from kallithea.lib.base import BaseController, render
40 from kallithea.lib.base import BaseController, render
@@ -114,11 +113,11 b' class SettingsController(BaseController)'
114
113
115 meta.Session().commit()
114 meta.Session().commit()
116
115
117 h.flash(_('Updated VCS settings'), category='success')
116 webutils.flash(_('Updated VCS settings'), category='success')
118
117
119 except Exception:
118 except Exception:
120 log.error(traceback.format_exc())
119 log.error(traceback.format_exc())
121 h.flash(_('Error occurred while updating '
120 webutils.flash(_('Error occurred while updating '
122 'application settings'), category='error')
121 'application settings'), category='error')
123
122
124 defaults = db.Setting.get_app_settings()
123 defaults = db.Setting.get_app_settings()
@@ -147,13 +146,13 b' class SettingsController(BaseController)'
147 install_git_hooks=install_git_hooks,
146 install_git_hooks=install_git_hooks,
148 user=request.authuser.username,
147 user=request.authuser.username,
149 overwrite_git_hooks=overwrite_git_hooks)
148 overwrite_git_hooks=overwrite_git_hooks)
150 added_msg = h.HTML(', ').join(
149 added_msg = webutils.HTML(', ').join(
151 h.link_to(safe_str(repo_name), webutils.url('summary_home', repo_name=repo_name)) for repo_name in added
150 webutils.link_to(safe_str(repo_name), webutils.url('summary_home', repo_name=repo_name)) for repo_name in added
152 ) or '-'
151 ) or '-'
153 removed_msg = h.HTML(', ').join(
152 removed_msg = webutils.HTML(', ').join(
154 safe_str(repo_name) for repo_name in removed
153 safe_str(repo_name) for repo_name in removed
155 ) or '-'
154 ) or '-'
156 h.flash(h.HTML(_('Repositories successfully rescanned. Added: %s. Removed: %s.')) %
155 webutils.flash(webutils.HTML(_('Repositories successfully rescanned. Added: %s. Removed: %s.')) %
157 (added_msg, removed_msg), category='success')
156 (added_msg, removed_msg), category='success')
158
157
159 if invalidate_cache:
158 if invalidate_cache:
@@ -165,7 +164,7 b' class SettingsController(BaseController)'
165 i += 1
164 i += 1
166 except VCSError as e:
165 except VCSError as e:
167 log.warning('VCS error invalidating %s: %s', repo.repo_name, e)
166 log.warning('VCS error invalidating %s: %s', repo.repo_name, e)
168 h.flash(_('Invalidated %s repositories') % i, category='success')
167 webutils.flash(_('Invalidated %s repositories') % i, category='success')
169
168
170 raise HTTPFound(location=url('admin_settings_mapping'))
169 raise HTTPFound(location=url('admin_settings_mapping'))
171
170
@@ -206,11 +205,11 b' class SettingsController(BaseController)'
206
205
207 meta.Session().commit()
206 meta.Session().commit()
208 set_app_settings(config)
207 set_app_settings(config)
209 h.flash(_('Updated application settings'), category='success')
208 webutils.flash(_('Updated application settings'), category='success')
210
209
211 except Exception:
210 except Exception:
212 log.error(traceback.format_exc())
211 log.error(traceback.format_exc())
213 h.flash(_('Error occurred while updating '
212 webutils.flash(_('Error occurred while updating '
214 'application settings'),
213 'application settings'),
215 category='error')
214 category='error')
216
215
@@ -260,12 +259,12 b' class SettingsController(BaseController)'
260
259
261 meta.Session().commit()
260 meta.Session().commit()
262 set_app_settings(config)
261 set_app_settings(config)
263 h.flash(_('Updated visualisation settings'),
262 webutils.flash(_('Updated visualisation settings'),
264 category='success')
263 category='success')
265
264
266 except Exception:
265 except Exception:
267 log.error(traceback.format_exc())
266 log.error(traceback.format_exc())
268 h.flash(_('Error occurred during updating '
267 webutils.flash(_('Error occurred during updating '
269 'visualisation settings'),
268 'visualisation settings'),
270 category='error')
269 category='error')
271
270
@@ -289,7 +288,7 b' class SettingsController(BaseController)'
289 test_body = ('Kallithea Email test, '
288 test_body = ('Kallithea Email test, '
290 'Kallithea version: %s' % c.kallithea_version)
289 'Kallithea version: %s' % c.kallithea_version)
291 if not test_email:
290 if not test_email:
292 h.flash(_('Please enter email address'), category='error')
291 webutils.flash(_('Please enter email address'), category='error')
293 raise HTTPFound(location=url('admin_settings_email'))
292 raise HTTPFound(location=url('admin_settings_email'))
294
293
295 test_email_txt_body = EmailNotificationModel() \
294 test_email_txt_body = EmailNotificationModel() \
@@ -304,7 +303,7 b' class SettingsController(BaseController)'
304 tasks.send_email(recipients, test_email_subj,
303 tasks.send_email(recipients, test_email_subj,
305 test_email_txt_body, test_email_html_body)
304 test_email_txt_body, test_email_html_body)
306
305
307 h.flash(_('Send email task created'), category='success')
306 webutils.flash(_('Send email task created'), category='success')
308 raise HTTPFound(location=url('admin_settings_email'))
307 raise HTTPFound(location=url('admin_settings_email'))
309
308
310 defaults = db.Setting.get_app_settings()
309 defaults = db.Setting.get_app_settings()
@@ -332,12 +331,12 b' class SettingsController(BaseController)'
332 try:
331 try:
333 ui_key = ui_key and ui_key.strip()
332 ui_key = ui_key and ui_key.strip()
334 if ui_key in (x.ui_key for x in db.Ui.get_custom_hooks()):
333 if ui_key in (x.ui_key for x in db.Ui.get_custom_hooks()):
335 h.flash(_('Hook already exists'), category='error')
334 webutils.flash(_('Hook already exists'), category='error')
336 elif ui_key in (x.ui_key for x in db.Ui.get_builtin_hooks()):
335 elif ui_key in (x.ui_key for x in db.Ui.get_builtin_hooks()):
337 h.flash(_('Builtin hooks are read-only. Please use another hook name.'), category='error')
336 webutils.flash(_('Builtin hooks are read-only. Please use another hook name.'), category='error')
338 elif ui_value and ui_key:
337 elif ui_value and ui_key:
339 db.Ui.create_or_update_hook(ui_key, ui_value)
338 db.Ui.create_or_update_hook(ui_key, ui_value)
340 h.flash(_('Added new hook'), category='success')
339 webutils.flash(_('Added new hook'), category='success')
341 elif hook_id:
340 elif hook_id:
342 db.Ui.delete(hook_id)
341 db.Ui.delete(hook_id)
343 meta.Session().commit()
342 meta.Session().commit()
@@ -353,11 +352,11 b' class SettingsController(BaseController)'
353 update = True
352 update = True
354
353
355 if update:
354 if update:
356 h.flash(_('Updated hooks'), category='success')
355 webutils.flash(_('Updated hooks'), category='success')
357 meta.Session().commit()
356 meta.Session().commit()
358 except Exception:
357 except Exception:
359 log.error(traceback.format_exc())
358 log.error(traceback.format_exc())
360 h.flash(_('Error occurred during hook creation'),
359 webutils.flash(_('Error occurred during hook creation'),
361 category='error')
360 category='error')
362
361
363 raise HTTPFound(location=url('admin_settings_hooks'))
362 raise HTTPFound(location=url('admin_settings_hooks'))
@@ -381,7 +380,7 b' class SettingsController(BaseController)'
381 repo_location = self._get_hg_ui_settings()['paths_root_path']
380 repo_location = self._get_hg_ui_settings()['paths_root_path']
382 full_index = request.POST.get('full_index', False)
381 full_index = request.POST.get('full_index', False)
383 tasks.whoosh_index(repo_location, full_index)
382 tasks.whoosh_index(repo_location, full_index)
384 h.flash(_('Whoosh reindex task scheduled'), category='success')
383 webutils.flash(_('Whoosh reindex task scheduled'), category='success')
385 raise HTTPFound(location=url('admin_settings_search'))
384 raise HTTPFound(location=url('admin_settings_search'))
386
385
387 defaults = db.Setting.get_app_settings()
386 defaults = db.Setting.get_app_settings()
@@ -38,6 +38,7 b' from tg.i18n import ugettext as _'
38 from webob.exc import HTTPFound, HTTPInternalServerError
38 from webob.exc import HTTPFound, HTTPInternalServerError
39
39
40 from kallithea.lib import helpers as h
40 from kallithea.lib import helpers as h
41 from kallithea.lib import webutils
41 from kallithea.lib.auth import HasPermissionAnyDecorator, HasUserGroupPermissionLevelDecorator, LoginRequired
42 from kallithea.lib.auth import HasPermissionAnyDecorator, HasUserGroupPermissionLevelDecorator, LoginRequired
42 from kallithea.lib.base import BaseController, render
43 from kallithea.lib.base import BaseController, render
43 from kallithea.lib.exceptions import RepoGroupAssignmentError, UserGroupsAssignedException
44 from kallithea.lib.exceptions import RepoGroupAssignmentError, UserGroupsAssignedException
@@ -100,7 +101,7 b' class UserGroupsController(BaseControlle'
100 "raw_name": user_gr.users_group_name,
101 "raw_name": user_gr.users_group_name,
101 "group_name": user_group_name(user_gr.users_group_id,
102 "group_name": user_group_name(user_gr.users_group_id,
102 user_gr.users_group_name),
103 user_gr.users_group_name),
103 "desc": h.escape(user_gr.user_group_description),
104 "desc": webutils.escape(user_gr.user_group_description),
104 "members": len(user_gr.members),
105 "members": len(user_gr.members),
105 "active": h.boolicon(user_gr.users_group_active),
106 "active": h.boolicon(user_gr.users_group_active),
106 "owner": h.person(user_gr.owner.username),
107 "owner": h.person(user_gr.owner.username),
@@ -129,7 +130,7 b' class UserGroupsController(BaseControlle'
129 action_logger(request.authuser,
130 action_logger(request.authuser,
130 'admin_created_users_group:%s' % gr,
131 'admin_created_users_group:%s' % gr,
131 None, request.ip_addr)
132 None, request.ip_addr)
132 h.flash(h.HTML(_('Created user group %s')) % h.link_to(gr, url('edit_users_group', id=ug.users_group_id)),
133 webutils.flash(webutils.HTML(_('Created user group %s')) % webutils.link_to(gr, url('edit_users_group', id=ug.users_group_id)),
133 category='success')
134 category='success')
134 meta.Session().commit()
135 meta.Session().commit()
135 except formencode.Invalid as errors:
136 except formencode.Invalid as errors:
@@ -142,7 +143,7 b' class UserGroupsController(BaseControlle'
142 force_defaults=False)
143 force_defaults=False)
143 except Exception:
144 except Exception:
144 log.error(traceback.format_exc())
145 log.error(traceback.format_exc())
145 h.flash(_('Error occurred during creation of user group %s')
146 webutils.flash(_('Error occurred during creation of user group %s')
146 % request.POST.get('users_group_name'), category='error')
147 % request.POST.get('users_group_name'), category='error')
147
148
148 raise HTTPFound(location=url('users_groups'))
149 raise HTTPFound(location=url('users_groups'))
@@ -170,7 +171,7 b' class UserGroupsController(BaseControlle'
170 action_logger(request.authuser,
171 action_logger(request.authuser,
171 'admin_updated_users_group:%s' % gr,
172 'admin_updated_users_group:%s' % gr,
172 None, request.ip_addr)
173 None, request.ip_addr)
173 h.flash(_('Updated user group %s') % gr, category='success')
174 webutils.flash(_('Updated user group %s') % gr, category='success')
174 meta.Session().commit()
175 meta.Session().commit()
175 except formencode.Invalid as errors:
176 except formencode.Invalid as errors:
176 ug_model = UserGroupModel()
177 ug_model = UserGroupModel()
@@ -192,7 +193,7 b' class UserGroupsController(BaseControlle'
192 force_defaults=False)
193 force_defaults=False)
193 except Exception:
194 except Exception:
194 log.error(traceback.format_exc())
195 log.error(traceback.format_exc())
195 h.flash(_('Error occurred during update of user group %s')
196 webutils.flash(_('Error occurred during update of user group %s')
196 % request.POST.get('users_group_name'), category='error')
197 % request.POST.get('users_group_name'), category='error')
197
198
198 raise HTTPFound(location=url('edit_users_group', id=id))
199 raise HTTPFound(location=url('edit_users_group', id=id))
@@ -203,12 +204,12 b' class UserGroupsController(BaseControlle'
203 try:
204 try:
204 UserGroupModel().delete(usr_gr)
205 UserGroupModel().delete(usr_gr)
205 meta.Session().commit()
206 meta.Session().commit()
206 h.flash(_('Successfully deleted user group'), category='success')
207 webutils.flash(_('Successfully deleted user group'), category='success')
207 except UserGroupsAssignedException as e:
208 except UserGroupsAssignedException as e:
208 h.flash(e, category='error')
209 webutils.flash(e, category='error')
209 except Exception:
210 except Exception:
210 log.error(traceback.format_exc())
211 log.error(traceback.format_exc())
211 h.flash(_('An error occurred during deletion of user group'),
212 webutils.flash(_('An error occurred during deletion of user group'),
212 category='error')
213 category='error')
213 raise HTTPFound(location=url('users_groups'))
214 raise HTTPFound(location=url('users_groups'))
214
215
@@ -264,13 +265,13 b' class UserGroupsController(BaseControlle'
264 UserGroupModel()._update_permissions(user_group, form['perms_new'],
265 UserGroupModel()._update_permissions(user_group, form['perms_new'],
265 form['perms_updates'])
266 form['perms_updates'])
266 except RepoGroupAssignmentError:
267 except RepoGroupAssignmentError:
267 h.flash(_('Target group cannot be the same'), category='error')
268 webutils.flash(_('Target group cannot be the same'), category='error')
268 raise HTTPFound(location=url('edit_user_group_perms', id=id))
269 raise HTTPFound(location=url('edit_user_group_perms', id=id))
269 # TODO: implement this
270 # TODO: implement this
270 #action_logger(request.authuser, 'admin_changed_repo_permissions',
271 #action_logger(request.authuser, 'admin_changed_repo_permissions',
271 # repo_name, request.ip_addr)
272 # repo_name, request.ip_addr)
272 meta.Session().commit()
273 meta.Session().commit()
273 h.flash(_('User group permissions updated'), category='success')
274 webutils.flash(_('User group permissions updated'), category='success')
274 raise HTTPFound(location=url('edit_user_group_perms', id=id))
275 raise HTTPFound(location=url('edit_user_group_perms', id=id))
275
276
276 @HasUserGroupPermissionLevelDecorator('admin')
277 @HasUserGroupPermissionLevelDecorator('admin')
@@ -286,7 +287,7 b' class UserGroupsController(BaseControlle'
286 if not request.authuser.is_admin:
287 if not request.authuser.is_admin:
287 if obj_type == 'user' and request.authuser.user_id == obj_id:
288 if obj_type == 'user' and request.authuser.user_id == obj_id:
288 msg = _('Cannot revoke permission for yourself as admin')
289 msg = _('Cannot revoke permission for yourself as admin')
289 h.flash(msg, category='warning')
290 webutils.flash(msg, category='warning')
290 raise Exception('revoke admin permission on self')
291 raise Exception('revoke admin permission on self')
291 if obj_type == 'user':
292 if obj_type == 'user':
292 UserGroupModel().revoke_user_permission(user_group=id,
293 UserGroupModel().revoke_user_permission(user_group=id,
@@ -297,7 +298,7 b' class UserGroupsController(BaseControlle'
297 meta.Session().commit()
298 meta.Session().commit()
298 except Exception:
299 except Exception:
299 log.error(traceback.format_exc())
300 log.error(traceback.format_exc())
300 h.flash(_('An error occurred during revoking of permission'),
301 webutils.flash(_('An error occurred during revoking of permission'),
301 category='error')
302 category='error')
302 raise HTTPInternalServerError()
303 raise HTTPInternalServerError()
303
304
@@ -379,11 +380,11 b' class UserGroupsController(BaseControlle'
379 else:
380 else:
380 usergroup_model.grant_perm(id, 'hg.fork.none')
381 usergroup_model.grant_perm(id, 'hg.fork.none')
381
382
382 h.flash(_("Updated permissions"), category='success')
383 webutils.flash(_("Updated permissions"), category='success')
383 meta.Session().commit()
384 meta.Session().commit()
384 except Exception:
385 except Exception:
385 log.error(traceback.format_exc())
386 log.error(traceback.format_exc())
386 h.flash(_('An error occurred during permissions saving'),
387 webutils.flash(_('An error occurred during permissions saving'),
387 category='error')
388 category='error')
388
389
389 raise HTTPFound(location=url('edit_user_group_default_perms', id=id))
390 raise HTTPFound(location=url('edit_user_group_default_perms', id=id))
@@ -39,6 +39,7 b' from webob.exc import HTTPFound, HTTPNot'
39 import kallithea
39 import kallithea
40 from kallithea.lib import auth_modules
40 from kallithea.lib import auth_modules
41 from kallithea.lib import helpers as h
41 from kallithea.lib import helpers as h
42 from kallithea.lib import webutils
42 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
43 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator, LoginRequired
43 from kallithea.lib.base import BaseController, IfSshEnabled, render
44 from kallithea.lib.base import BaseController, IfSshEnabled, render
44 from kallithea.lib.exceptions import DefaultUserException, UserCreationError, UserOwnsReposException
45 from kallithea.lib.exceptions import DefaultUserException, UserCreationError, UserOwnsReposException
@@ -87,8 +88,8 b' class UsersController(BaseController):'
87 "gravatar": grav_tmpl % h.gravatar(user.email, size=20),
88 "gravatar": grav_tmpl % h.gravatar(user.email, size=20),
88 "raw_name": user.username,
89 "raw_name": user.username,
89 "username": username(user.user_id, user.username),
90 "username": username(user.user_id, user.username),
90 "firstname": h.escape(user.name),
91 "firstname": webutils.escape(user.name),
91 "lastname": h.escape(user.lastname),
92 "lastname": webutils.escape(user.lastname),
92 "last_login": h.fmt_date(user.last_login),
93 "last_login": h.fmt_date(user.last_login),
93 "last_login_raw": datetime_to_time(user.last_login),
94 "last_login_raw": datetime_to_time(user.last_login),
94 "active": h.boolicon(user.active),
95 "active": h.boolicon(user.active),
@@ -116,7 +117,7 b' class UsersController(BaseController):'
116 user = user_model.create(form_result)
117 user = user_model.create(form_result)
117 action_logger(request.authuser, 'admin_created_user:%s' % user.username,
118 action_logger(request.authuser, 'admin_created_user:%s' % user.username,
118 None, request.ip_addr)
119 None, request.ip_addr)
119 h.flash(_('Created user %s') % user.username,
120 webutils.flash(_('Created user %s') % user.username,
120 category='success')
121 category='success')
121 meta.Session().commit()
122 meta.Session().commit()
122 except formencode.Invalid as errors:
123 except formencode.Invalid as errors:
@@ -128,10 +129,10 b' class UsersController(BaseController):'
128 encoding="UTF-8",
129 encoding="UTF-8",
129 force_defaults=False)
130 force_defaults=False)
130 except UserCreationError as e:
131 except UserCreationError as e:
131 h.flash(e, 'error')
132 webutils.flash(e, 'error')
132 except Exception:
133 except Exception:
133 log.error(traceback.format_exc())
134 log.error(traceback.format_exc())
134 h.flash(_('Error occurred during creation of user %s')
135 webutils.flash(_('Error occurred during creation of user %s')
135 % request.POST.get('username'), category='error')
136 % request.POST.get('username'), category='error')
136 raise HTTPFound(location=url('edit_user', id=user.user_id))
137 raise HTTPFound(location=url('edit_user', id=user.user_id))
137
138
@@ -155,7 +156,7 b' class UsersController(BaseController):'
155 usr = form_result['username']
156 usr = form_result['username']
156 action_logger(request.authuser, 'admin_updated_user:%s' % usr,
157 action_logger(request.authuser, 'admin_updated_user:%s' % usr,
157 None, request.ip_addr)
158 None, request.ip_addr)
158 h.flash(_('User updated successfully'), category='success')
159 webutils.flash(_('User updated successfully'), category='success')
159 meta.Session().commit()
160 meta.Session().commit()
160 except formencode.Invalid as errors:
161 except formencode.Invalid as errors:
161 defaults = errors.value
162 defaults = errors.value
@@ -174,7 +175,7 b' class UsersController(BaseController):'
174 force_defaults=False)
175 force_defaults=False)
175 except Exception:
176 except Exception:
176 log.error(traceback.format_exc())
177 log.error(traceback.format_exc())
177 h.flash(_('Error occurred during update of user %s')
178 webutils.flash(_('Error occurred during update of user %s')
178 % form_result.get('username'), category='error')
179 % form_result.get('username'), category='error')
179 raise HTTPFound(location=url('edit_user', id=id))
180 raise HTTPFound(location=url('edit_user', id=id))
180
181
@@ -184,12 +185,12 b' class UsersController(BaseController):'
184 try:
185 try:
185 UserModel().delete(usr)
186 UserModel().delete(usr)
186 meta.Session().commit()
187 meta.Session().commit()
187 h.flash(_('Successfully deleted user'), category='success')
188 webutils.flash(_('Successfully deleted user'), category='success')
188 except (UserOwnsReposException, DefaultUserException) as e:
189 except (UserOwnsReposException, DefaultUserException) as e:
189 h.flash(e, category='warning')
190 webutils.flash(e, category='warning')
190 except Exception:
191 except Exception:
191 log.error(traceback.format_exc())
192 log.error(traceback.format_exc())
192 h.flash(_('An error occurred during deletion of user'),
193 webutils.flash(_('An error occurred during deletion of user'),
193 category='error')
194 category='error')
194 else:
195 else:
195 if has_ssh_keys:
196 if has_ssh_keys:
@@ -200,7 +201,7 b' class UsersController(BaseController):'
200 try:
201 try:
201 return db.User.get_or_404(id, allow_default=False)
202 return db.User.get_or_404(id, allow_default=False)
202 except DefaultUserException:
203 except DefaultUserException:
203 h.flash(_("The default user cannot be edited"), category='warning')
204 webutils.flash(_("The default user cannot be edited"), category='warning')
204 raise HTTPNotFound
205 raise HTTPNotFound
205
206
206 def _render_edit_profile(self, user):
207 def _render_edit_profile(self, user):
@@ -268,7 +269,7 b' class UsersController(BaseController):'
268 description = request.POST.get('description')
269 description = request.POST.get('description')
269 ApiKeyModel().create(c.user.user_id, description, lifetime)
270 ApiKeyModel().create(c.user.user_id, description, lifetime)
270 meta.Session().commit()
271 meta.Session().commit()
271 h.flash(_("API key successfully created"), category='success')
272 webutils.flash(_("API key successfully created"), category='success')
272 raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
273 raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
273
274
274 def delete_api_key(self, id):
275 def delete_api_key(self, id):
@@ -278,11 +279,11 b' class UsersController(BaseController):'
278 if request.POST.get('del_api_key_builtin'):
279 if request.POST.get('del_api_key_builtin'):
279 c.user.api_key = generate_api_key()
280 c.user.api_key = generate_api_key()
280 meta.Session().commit()
281 meta.Session().commit()
281 h.flash(_("API key successfully reset"), category='success')
282 webutils.flash(_("API key successfully reset"), category='success')
282 elif api_key:
283 elif api_key:
283 ApiKeyModel().delete(api_key, c.user.user_id)
284 ApiKeyModel().delete(api_key, c.user.user_id)
284 meta.Session().commit()
285 meta.Session().commit()
285 h.flash(_("API key successfully deleted"), category='success')
286 webutils.flash(_("API key successfully deleted"), category='success')
286
287
287 raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
288 raise HTTPFound(location=url('edit_user_api_keys', id=c.user.user_id))
288
289
@@ -335,11 +336,11 b' class UsersController(BaseController):'
335 user_model.grant_perm(id, 'hg.fork.repository')
336 user_model.grant_perm(id, 'hg.fork.repository')
336 else:
337 else:
337 user_model.grant_perm(id, 'hg.fork.none')
338 user_model.grant_perm(id, 'hg.fork.none')
338 h.flash(_("Updated permissions"), category='success')
339 webutils.flash(_("Updated permissions"), category='success')
339 meta.Session().commit()
340 meta.Session().commit()
340 except Exception:
341 except Exception:
341 log.error(traceback.format_exc())
342 log.error(traceback.format_exc())
342 h.flash(_('An error occurred during permissions saving'),
343 webutils.flash(_('An error occurred during permissions saving'),
343 category='error')
344 category='error')
344 raise HTTPFound(location=url('edit_user_perms', id=id))
345 raise HTTPFound(location=url('edit_user_perms', id=id))
345
346
@@ -364,13 +365,13 b' class UsersController(BaseController):'
364 try:
365 try:
365 user_model.add_extra_email(id, email)
366 user_model.add_extra_email(id, email)
366 meta.Session().commit()
367 meta.Session().commit()
367 h.flash(_("Added email %s to user") % email, category='success')
368 webutils.flash(_("Added email %s to user") % email, category='success')
368 except formencode.Invalid as error:
369 except formencode.Invalid as error:
369 msg = error.error_dict['email']
370 msg = error.error_dict['email']
370 h.flash(msg, category='error')
371 webutils.flash(msg, category='error')
371 except Exception:
372 except Exception:
372 log.error(traceback.format_exc())
373 log.error(traceback.format_exc())
373 h.flash(_('An error occurred during email saving'),
374 webutils.flash(_('An error occurred during email saving'),
374 category='error')
375 category='error')
375 raise HTTPFound(location=url('edit_user_emails', id=id))
376 raise HTTPFound(location=url('edit_user_emails', id=id))
376
377
@@ -380,7 +381,7 b' class UsersController(BaseController):'
380 user_model = UserModel()
381 user_model = UserModel()
381 user_model.delete_extra_email(id, email_id)
382 user_model.delete_extra_email(id, email_id)
382 meta.Session().commit()
383 meta.Session().commit()
383 h.flash(_("Removed email from user"), category='success')
384 webutils.flash(_("Removed email from user"), category='success')
384 raise HTTPFound(location=url('edit_user_emails', id=id))
385 raise HTTPFound(location=url('edit_user_emails', id=id))
385
386
386 def edit_ips(self, id):
387 def edit_ips(self, id):
@@ -406,13 +407,13 b' class UsersController(BaseController):'
406 try:
407 try:
407 user_model.add_extra_ip(id, ip)
408 user_model.add_extra_ip(id, ip)
408 meta.Session().commit()
409 meta.Session().commit()
409 h.flash(_("Added IP address %s to user whitelist") % ip, category='success')
410 webutils.flash(_("Added IP address %s to user whitelist") % ip, category='success')
410 except formencode.Invalid as error:
411 except formencode.Invalid as error:
411 msg = error.error_dict['ip']
412 msg = error.error_dict['ip']
412 h.flash(msg, category='error')
413 webutils.flash(msg, category='error')
413 except Exception:
414 except Exception:
414 log.error(traceback.format_exc())
415 log.error(traceback.format_exc())
415 h.flash(_('An error occurred while adding IP address'),
416 webutils.flash(_('An error occurred while adding IP address'),
416 category='error')
417 category='error')
417
418
418 if 'default_user' in request.POST:
419 if 'default_user' in request.POST:
@@ -424,7 +425,7 b' class UsersController(BaseController):'
424 user_model = UserModel()
425 user_model = UserModel()
425 user_model.delete_extra_ip(id, ip_id)
426 user_model.delete_extra_ip(id, ip_id)
426 meta.Session().commit()
427 meta.Session().commit()
427 h.flash(_("Removed IP address from user whitelist"), category='success')
428 webutils.flash(_("Removed IP address from user whitelist"), category='success')
428
429
429 if 'default_user' in request.POST:
430 if 'default_user' in request.POST:
430 raise HTTPFound(location=url('admin_permissions_ips'))
431 raise HTTPFound(location=url('admin_permissions_ips'))
@@ -453,9 +454,9 b' class UsersController(BaseController):'
453 description, public_key)
454 description, public_key)
454 meta.Session().commit()
455 meta.Session().commit()
455 SshKeyModel().write_authorized_keys()
456 SshKeyModel().write_authorized_keys()
456 h.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
457 webutils.flash(_("SSH key %s successfully added") % new_ssh_key.fingerprint, category='success')
457 except SshKeyModelException as e:
458 except SshKeyModelException as e:
458 h.flash(e.args[0], category='error')
459 webutils.flash(e.args[0], category='error')
459 raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id))
460 raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id))
460
461
461 @IfSshEnabled
462 @IfSshEnabled
@@ -467,7 +468,7 b' class UsersController(BaseController):'
467 SshKeyModel().delete(fingerprint, c.user.user_id)
468 SshKeyModel().delete(fingerprint, c.user.user_id)
468 meta.Session().commit()
469 meta.Session().commit()
469 SshKeyModel().write_authorized_keys()
470 SshKeyModel().write_authorized_keys()
470 h.flash(_("SSH key successfully deleted"), category='success')
471 webutils.flash(_("SSH key successfully deleted"), category='success')
471 except SshKeyModelException as e:
472 except SshKeyModelException as e:
472 h.flash(e.args[0], category='error')
473 webutils.flash(e.args[0], category='error')
473 raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id))
474 raise HTTPFound(location=url('edit_user_ssh_keys', id=c.user.user_id))
@@ -33,7 +33,6 b' from tg import tmpl_context as c'
33 from tg.i18n import ugettext as _
33 from tg.i18n import ugettext as _
34 from webob.exc import HTTPBadRequest, HTTPFound, HTTPNotFound
34 from webob.exc import HTTPBadRequest, HTTPFound, HTTPNotFound
35
35
36 import kallithea.lib.helpers as h
37 from kallithea.lib import webutils
36 from kallithea.lib import webutils
38 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
37 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
39 from kallithea.lib.base import BaseRepoController, render
38 from kallithea.lib.base import BaseRepoController, render
@@ -65,10 +64,10 b' class ChangelogController(BaseRepoContro'
65 try:
64 try:
66 return c.db_repo_scm_instance.get_changeset(rev)
65 return c.db_repo_scm_instance.get_changeset(rev)
67 except EmptyRepositoryError as e:
66 except EmptyRepositoryError as e:
68 h.flash(_('There are no changesets yet'), category='error')
67 webutils.flash(_('There are no changesets yet'), category='error')
69 except RepositoryError as e:
68 except RepositoryError as e:
70 log.error(traceback.format_exc())
69 log.error(traceback.format_exc())
71 h.flash(e, category='error')
70 webutils.flash(e, category='error')
72 raise HTTPBadRequest()
71 raise HTTPBadRequest()
73
72
74 @LoginRequired(allow_default_user=True)
73 @LoginRequired(allow_default_user=True)
@@ -112,7 +111,7 b' class ChangelogController(BaseRepoContro'
112 cs = self.__get_cs(revision, repo_name)
111 cs = self.__get_cs(revision, repo_name)
113 collection = cs.get_file_history(f_path)
112 collection = cs.get_file_history(f_path)
114 except RepositoryError as e:
113 except RepositoryError as e:
115 h.flash(e, category='warning')
114 webutils.flash(e, category='warning')
116 raise HTTPFound(location=webutils.url('changelog_home', repo_name=repo_name))
115 raise HTTPFound(location=webutils.url('changelog_home', repo_name=repo_name))
117 else:
116 else:
118 collection = c.db_repo_scm_instance.get_changesets(start=0, end=revision,
117 collection = c.db_repo_scm_instance.get_changesets(start=0, end=revision,
@@ -126,11 +125,11 b' class ChangelogController(BaseRepoContro'
126 c.cs_comments = c.db_repo.get_comments(page_revisions)
125 c.cs_comments = c.db_repo.get_comments(page_revisions)
127 c.cs_statuses = c.db_repo.statuses(page_revisions)
126 c.cs_statuses = c.db_repo.statuses(page_revisions)
128 except EmptyRepositoryError as e:
127 except EmptyRepositoryError as e:
129 h.flash(e, category='warning')
128 webutils.flash(e, category='warning')
130 raise HTTPFound(location=url('summary_home', repo_name=c.repo_name))
129 raise HTTPFound(location=url('summary_home', repo_name=c.repo_name))
131 except (RepositoryError, ChangesetDoesNotExistError, Exception) as e:
130 except (RepositoryError, ChangesetDoesNotExistError, Exception) as e:
132 log.error(traceback.format_exc())
131 log.error(traceback.format_exc())
133 h.flash(e, category='error')
132 webutils.flash(e, category='error')
134 raise HTTPFound(location=url('changelog_home', repo_name=c.repo_name))
133 raise HTTPFound(location=url('changelog_home', repo_name=c.repo_name))
135
134
136 c.branch_name = branch_name
135 c.branch_name = branch_name
@@ -86,7 +86,7 b' def create_cs_pr_comment(repo_name, revi'
86
86
87 if not allowed_to_change_status:
87 if not allowed_to_change_status:
88 if status or close_pr:
88 if status or close_pr:
89 h.flash(_('No permission to change status'), 'error')
89 webutils.flash(_('No permission to change status'), 'error')
90 raise HTTPForbidden()
90 raise HTTPForbidden()
91
91
92 if pull_request and delete == "delete":
92 if pull_request and delete == "delete":
@@ -97,7 +97,7 b' def create_cs_pr_comment(repo_name, revi'
97 ) and not pull_request.is_closed():
97 ) and not pull_request.is_closed():
98 PullRequestModel().delete(pull_request)
98 PullRequestModel().delete(pull_request)
99 meta.Session().commit()
99 meta.Session().commit()
100 h.flash(_('Successfully deleted pull request %s') % pull_request_id,
100 webutils.flash(_('Successfully deleted pull request %s') % pull_request_id,
101 category='success')
101 category='success')
102 return {
102 return {
103 'location': webutils.url('my_pullrequests'), # or repo pr list?
103 'location': webutils.url('my_pullrequests'), # or repo pr list?
@@ -143,7 +143,7 b' def create_cs_pr_comment(repo_name, revi'
143 meta.Session().commit()
143 meta.Session().commit()
144
144
145 data = {
145 data = {
146 'target_id': h.safeid(request.POST.get('f_path')),
146 'target_id': webutils.safeid(request.POST.get('f_path')),
147 }
147 }
148 if comment is not None:
148 if comment is not None:
149 c.comment = comment
149 c.comment = comment
@@ -199,7 +199,7 b' class ChangesetController(BaseRepoContro'
199 except (ChangesetDoesNotExistError, EmptyRepositoryError):
199 except (ChangesetDoesNotExistError, EmptyRepositoryError):
200 log.debug(traceback.format_exc())
200 log.debug(traceback.format_exc())
201 msg = _('Such revision does not exist for this repository')
201 msg = _('Such revision does not exist for this repository')
202 h.flash(msg, category='error')
202 webutils.flash(msg, category='error')
203 raise HTTPNotFound()
203 raise HTTPNotFound()
204
204
205 c.changes = OrderedDict()
205 c.changes = OrderedDict()
@@ -63,13 +63,13 b' class CompareController(BaseRepoControll'
63 c.cs_repo = db.Repository.get_by_repo_name(other_repo)
63 c.cs_repo = db.Repository.get_by_repo_name(other_repo)
64 if c.cs_repo is None:
64 if c.cs_repo is None:
65 msg = _('Could not find other repository %s') % other_repo
65 msg = _('Could not find other repository %s') % other_repo
66 h.flash(msg, category='error')
66 webutils.flash(msg, category='error')
67 raise HTTPFound(location=url('compare_home', repo_name=c.a_repo.repo_name))
67 raise HTTPFound(location=url('compare_home', repo_name=c.a_repo.repo_name))
68
68
69 # Verify that it's even possible to compare these two repositories.
69 # Verify that it's even possible to compare these two repositories.
70 if c.a_repo.scm_instance.alias != c.cs_repo.scm_instance.alias:
70 if c.a_repo.scm_instance.alias != c.cs_repo.scm_instance.alias:
71 msg = _('Cannot compare repositories of different types')
71 msg = _('Cannot compare repositories of different types')
72 h.flash(msg, category='error')
72 webutils.flash(msg, category='error')
73 raise HTTPFound(location=url('compare_home', repo_name=c.a_repo.repo_name))
73 raise HTTPFound(location=url('compare_home', repo_name=c.a_repo.repo_name))
74
74
75 @LoginRequired(allow_default_user=True)
75 @LoginRequired(allow_default_user=True)
@@ -146,7 +146,7 b' class CompareController(BaseRepoControll'
146 else:
146 else:
147 msg = _('Multiple merge ancestors found for merge compare')
147 msg = _('Multiple merge ancestors found for merge compare')
148 if rev1 is None:
148 if rev1 is None:
149 h.flash(msg, category='error')
149 webutils.flash(msg, category='error')
150 log.error(msg)
150 log.error(msg)
151 raise HTTPNotFound
151 raise HTTPNotFound
152
152
@@ -160,7 +160,7 b' class CompareController(BaseRepoControll'
160 if org_repo != other_repo:
160 if org_repo != other_repo:
161 # TODO: we could do this by using hg unionrepo
161 # TODO: we could do this by using hg unionrepo
162 log.error('cannot compare across repos %s and %s', org_repo, other_repo)
162 log.error('cannot compare across repos %s and %s', org_repo, other_repo)
163 h.flash(_('Cannot compare repositories without using common ancestor'), category='error')
163 webutils.flash(_('Cannot compare repositories without using common ancestor'), category='error')
164 raise HTTPBadRequest
164 raise HTTPBadRequest
165 rev1 = c.a_rev
165 rev1 = c.a_rev
166
166
@@ -83,15 +83,15 b' class FilesController(BaseRepoController'
83 url_ = url('files_add_home',
83 url_ = url('files_add_home',
84 repo_name=c.repo_name,
84 repo_name=c.repo_name,
85 revision=0, f_path='', anchor='edit')
85 revision=0, f_path='', anchor='edit')
86 add_new = h.link_to(_('Click here to add new file'), url_, class_="alert-link")
86 add_new = webutils.link_to(_('Click here to add new file'), url_, class_="alert-link")
87 h.flash(_('There are no files yet.') + ' ' + add_new, category='warning')
87 webutils.flash(_('There are no files yet.') + ' ' + add_new, category='warning')
88 raise HTTPNotFound()
88 raise HTTPNotFound()
89 except (ChangesetDoesNotExistError, LookupError):
89 except (ChangesetDoesNotExistError, LookupError):
90 msg = _('Such revision does not exist for this repository')
90 msg = _('Such revision does not exist for this repository')
91 h.flash(msg, category='error')
91 webutils.flash(msg, category='error')
92 raise HTTPNotFound()
92 raise HTTPNotFound()
93 except RepositoryError as e:
93 except RepositoryError as e:
94 h.flash(e, category='error')
94 webutils.flash(e, category='error')
95 raise HTTPNotFound()
95 raise HTTPNotFound()
96
96
97 def __get_filenode(self, cs, path):
97 def __get_filenode(self, cs, path):
@@ -108,10 +108,10 b' class FilesController(BaseRepoController'
108 raise RepositoryError('given path is a directory')
108 raise RepositoryError('given path is a directory')
109 except ChangesetDoesNotExistError:
109 except ChangesetDoesNotExistError:
110 msg = _('Such revision does not exist for this repository')
110 msg = _('Such revision does not exist for this repository')
111 h.flash(msg, category='error')
111 webutils.flash(msg, category='error')
112 raise HTTPNotFound()
112 raise HTTPNotFound()
113 except RepositoryError as e:
113 except RepositoryError as e:
114 h.flash(e, category='error')
114 webutils.flash(e, category='error')
115 raise HTTPNotFound()
115 raise HTTPNotFound()
116
116
117 return file_node
117 return file_node
@@ -176,7 +176,7 b' class FilesController(BaseRepoController'
176 else:
176 else:
177 c.authors = c.file_history = []
177 c.authors = c.file_history = []
178 except RepositoryError as e:
178 except RepositoryError as e:
179 h.flash(e, category='error')
179 webutils.flash(e, category='error')
180 raise HTTPNotFound()
180 raise HTTPNotFound()
181
181
182 if request.environ.get('HTTP_X_PARTIAL_XHR'):
182 if request.environ.get('HTTP_X_PARTIAL_XHR'):
@@ -293,7 +293,7 b' class FilesController(BaseRepoController'
293 _branches = repo.scm_instance.branches
293 _branches = repo.scm_instance.branches
294 # check if revision is a branch name or branch hash
294 # check if revision is a branch name or branch hash
295 if revision not in _branches and revision not in _branches.values():
295 if revision not in _branches and revision not in _branches.values():
296 h.flash(_('You can only delete files with revision '
296 webutils.flash(_('You can only delete files with revision '
297 'being a valid branch'), category='warning')
297 'being a valid branch'), category='warning')
298 raise HTTPFound(location=webutils.url('files_home',
298 raise HTTPFound(location=webutils.url('files_home',
299 repo_name=repo_name, revision='tip',
299 repo_name=repo_name, revision='tip',
@@ -328,11 +328,11 b' class FilesController(BaseRepoController'
328 author=author,
328 author=author,
329 )
329 )
330
330
331 h.flash(_('Successfully deleted file %s') % f_path,
331 webutils.flash(_('Successfully deleted file %s') % f_path,
332 category='success')
332 category='success')
333 except Exception:
333 except Exception:
334 log.error(traceback.format_exc())
334 log.error(traceback.format_exc())
335 h.flash(_('Error occurred during commit'), category='error')
335 webutils.flash(_('Error occurred during commit'), category='error')
336 raise HTTPFound(location=url('changeset_home',
336 raise HTTPFound(location=url('changeset_home',
337 repo_name=c.repo_name, revision='tip'))
337 repo_name=c.repo_name, revision='tip'))
338
338
@@ -347,7 +347,7 b' class FilesController(BaseRepoController'
347 _branches = repo.scm_instance.branches
347 _branches = repo.scm_instance.branches
348 # check if revision is a branch name or branch hash
348 # check if revision is a branch name or branch hash
349 if revision not in _branches and revision not in _branches.values():
349 if revision not in _branches and revision not in _branches.values():
350 h.flash(_('You can only edit files with revision '
350 webutils.flash(_('You can only edit files with revision '
351 'being a valid branch'), category='warning')
351 'being a valid branch'), category='warning')
352 raise HTTPFound(location=webutils.url('files_home',
352 raise HTTPFound(location=webutils.url('files_home',
353 repo_name=repo_name, revision='tip',
353 repo_name=repo_name, revision='tip',
@@ -376,7 +376,7 b' class FilesController(BaseRepoController'
376 author = request.authuser.full_contact
376 author = request.authuser.full_contact
377
377
378 if content == old_content:
378 if content == old_content:
379 h.flash(_('No changes'), category='warning')
379 webutils.flash(_('No changes'), category='warning')
380 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
380 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
381 revision='tip'))
381 revision='tip'))
382 try:
382 try:
@@ -386,11 +386,11 b' class FilesController(BaseRepoController'
386 ip_addr=request.ip_addr,
386 ip_addr=request.ip_addr,
387 author=author, message=message,
387 author=author, message=message,
388 content=content, f_path=f_path)
388 content=content, f_path=f_path)
389 h.flash(_('Successfully committed to %s') % f_path,
389 webutils.flash(_('Successfully committed to %s') % f_path,
390 category='success')
390 category='success')
391 except Exception:
391 except Exception:
392 log.error(traceback.format_exc())
392 log.error(traceback.format_exc())
393 h.flash(_('Error occurred during commit'), category='error')
393 webutils.flash(_('Error occurred during commit'), category='error')
394 raise HTTPFound(location=url('changeset_home',
394 raise HTTPFound(location=url('changeset_home',
395 repo_name=c.repo_name, revision='tip'))
395 repo_name=c.repo_name, revision='tip'))
396
396
@@ -426,11 +426,11 b' class FilesController(BaseRepoController'
426 content = content.file
426 content = content.file
427
427
428 if not content:
428 if not content:
429 h.flash(_('No content'), category='warning')
429 webutils.flash(_('No content'), category='warning')
430 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
430 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
431 revision='tip'))
431 revision='tip'))
432 if not filename:
432 if not filename:
433 h.flash(_('No filename'), category='warning')
433 webutils.flash(_('No filename'), category='warning')
434 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
434 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
435 revision='tip'))
435 revision='tip'))
436 # strip all crap out of file, just leave the basename
436 # strip all crap out of file, just leave the basename
@@ -454,18 +454,18 b' class FilesController(BaseRepoController'
454 author=author,
454 author=author,
455 )
455 )
456
456
457 h.flash(_('Successfully committed to %s') % node_path,
457 webutils.flash(_('Successfully committed to %s') % node_path,
458 category='success')
458 category='success')
459 except NonRelativePathError as e:
459 except NonRelativePathError as e:
460 h.flash(_('Location must be relative path and must not '
460 webutils.flash(_('Location must be relative path and must not '
461 'contain .. in path'), category='warning')
461 'contain .. in path'), category='warning')
462 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
462 raise HTTPFound(location=url('changeset_home', repo_name=c.repo_name,
463 revision='tip'))
463 revision='tip'))
464 except (NodeError, NodeAlreadyExistsError) as e:
464 except (NodeError, NodeAlreadyExistsError) as e:
465 h.flash(_(e), category='error')
465 webutils.flash(_(e), category='error')
466 except Exception:
466 except Exception:
467 log.error(traceback.format_exc())
467 log.error(traceback.format_exc())
468 h.flash(_('Error occurred during commit'), category='error')
468 webutils.flash(_('Error occurred during commit'), category='error')
469 raise HTTPFound(location=url('changeset_home',
469 raise HTTPFound(location=url('changeset_home',
470 repo_name=c.repo_name, revision='tip'))
470 repo_name=c.repo_name, revision='tip'))
471
471
@@ -687,7 +687,7 b' class FilesController(BaseRepoController'
687 node2 = FileNode(f_path, '', changeset=c.changeset_2)
687 node2 = FileNode(f_path, '', changeset=c.changeset_2)
688 except ChangesetDoesNotExistError as e:
688 except ChangesetDoesNotExistError as e:
689 msg = _('Such revision does not exist for this repository')
689 msg = _('Such revision does not exist for this repository')
690 h.flash(msg, category='error')
690 webutils.flash(msg, category='error')
691 raise HTTPNotFound()
691 raise HTTPNotFound()
692 c.node1 = node1
692 c.node1 = node1
693 c.node2 = node2
693 c.node2 = node2
@@ -36,7 +36,6 b' from tg.i18n import ugettext as _'
36 from webob.exc import HTTPFound, HTTPNotFound
36 from webob.exc import HTTPFound, HTTPNotFound
37
37
38 import kallithea
38 import kallithea
39 import kallithea.lib.helpers as h
40 from kallithea.lib import webutils
39 from kallithea.lib import webutils
41 from kallithea.lib.auth import HasPermissionAnyDecorator, HasRepoPermissionLevel, HasRepoPermissionLevelDecorator, LoginRequired
40 from kallithea.lib.auth import HasPermissionAnyDecorator, HasRepoPermissionLevel, HasRepoPermissionLevelDecorator, LoginRequired
42 from kallithea.lib.base import BaseRepoController, render
41 from kallithea.lib.base import BaseRepoController, render
@@ -166,7 +165,7 b' class ForksController(BaseRepoController'
166 force_defaults=False)
165 force_defaults=False)
167 except Exception:
166 except Exception:
168 log.error(traceback.format_exc())
167 log.error(traceback.format_exc())
169 h.flash(_('An error occurred during repository forking %s') %
168 webutils.flash(_('An error occurred during repository forking %s') %
170 repo_name, category='error')
169 repo_name, category='error')
171
170
172 raise HTTPFound(location=webutils.url('repo_creating_home',
171 raise HTTPFound(location=webutils.url('repo_creating_home',
@@ -36,7 +36,7 b' from tg import tmpl_context as c'
36 from tg.i18n import ugettext as _
36 from tg.i18n import ugettext as _
37 from webob.exc import HTTPBadRequest, HTTPFound
37 from webob.exc import HTTPBadRequest, HTTPFound
38
38
39 import kallithea.lib.helpers as h
39 from kallithea.lib import webutils
40 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator
40 from kallithea.lib.auth import AuthUser, HasPermissionAnyDecorator
41 from kallithea.lib.base import BaseController, log_in_user, render
41 from kallithea.lib.base import BaseController, log_in_user, render
42 from kallithea.lib.exceptions import UserCreationError
42 from kallithea.lib.exceptions import UserCreationError
@@ -99,13 +99,13 b' class LoginController(BaseController):'
99 # the fly can throw this exception signaling that there's issue
99 # the fly can throw this exception signaling that there's issue
100 # with user creation, explanation should be provided in
100 # with user creation, explanation should be provided in
101 # Exception itself
101 # Exception itself
102 h.flash(e, 'error')
102 webutils.flash(e, 'error')
103 else:
103 else:
104 # login_form already validated the password - now set the session cookie accordingly
104 # login_form already validated the password - now set the session cookie accordingly
105 auth_user = log_in_user(user, c.form_result['remember'], is_external_auth=False, ip_addr=request.ip_addr)
105 auth_user = log_in_user(user, c.form_result['remember'], is_external_auth=False, ip_addr=request.ip_addr)
106 if auth_user:
106 if auth_user:
107 raise HTTPFound(location=c.came_from)
107 raise HTTPFound(location=c.came_from)
108 h.flash(_('Authentication failed.'), 'error')
108 webutils.flash(_('Authentication failed.'), 'error')
109 else:
109 else:
110 # redirect if already logged in
110 # redirect if already logged in
111 if not request.authuser.is_anonymous:
111 if not request.authuser.is_anonymous:
@@ -144,7 +144,7 b' class LoginController(BaseController):'
144 error_dict=error_dict)
144 error_dict=error_dict)
145
145
146 UserModel().create_registration(form_result)
146 UserModel().create_registration(form_result)
147 h.flash(_('You have successfully registered with %s') % (c.site_name or 'Kallithea'),
147 webutils.flash(_('You have successfully registered with %s') % (c.site_name or 'Kallithea'),
148 category='success')
148 category='success')
149 meta.Session().commit()
149 meta.Session().commit()
150 raise HTTPFound(location=url('login_home'))
150 raise HTTPFound(location=url('login_home'))
@@ -162,7 +162,7 b' class LoginController(BaseController):'
162 # the fly can throw this exception signaling that there's issue
162 # the fly can throw this exception signaling that there's issue
163 # with user creation, explanation should be provided in
163 # with user creation, explanation should be provided in
164 # Exception itself
164 # Exception itself
165 h.flash(e, 'error')
165 webutils.flash(e, 'error')
166
166
167 return render('/register.html')
167 return render('/register.html')
168
168
@@ -188,7 +188,7 b' class LoginController(BaseController):'
188 raise formencode.Invalid(_msg, _value, None,
188 raise formencode.Invalid(_msg, _value, None,
189 error_dict=error_dict)
189 error_dict=error_dict)
190 redirect_link = UserModel().send_reset_password_email(form_result)
190 redirect_link = UserModel().send_reset_password_email(form_result)
191 h.flash(_('A password reset confirmation code has been sent'),
191 webutils.flash(_('A password reset confirmation code has been sent'),
192 category='success')
192 category='success')
193 raise HTTPFound(location=redirect_link)
193 raise HTTPFound(location=redirect_link)
194
194
@@ -240,7 +240,7 b' class LoginController(BaseController):'
240 encoding='UTF-8')
240 encoding='UTF-8')
241
241
242 UserModel().reset_password(form_result['email'], form_result['password'])
242 UserModel().reset_password(form_result['email'], form_result['password'])
243 h.flash(_('Successfully updated password'), category='success')
243 webutils.flash(_('Successfully updated password'), category='success')
244 raise HTTPFound(location=url('login_home'))
244 raise HTTPFound(location=url('login_home'))
245
245
246 def logout(self):
246 def logout(self):
@@ -254,4 +254,4 b' class LoginController(BaseController):'
254 Only intended for testing but might also be useful for other kinds
254 Only intended for testing but might also be useful for other kinds
255 of automation.
255 of automation.
256 """
256 """
257 return h.session_csrf_secret_token()
257 return webutils.session_csrf_secret_token()
@@ -35,9 +35,9 b' from tg import tmpl_context as c'
35 from tg.i18n import ugettext as _
35 from tg.i18n import ugettext as _
36 from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPFound, HTTPNotFound
36 from webob.exc import HTTPBadRequest, HTTPForbidden, HTTPFound, HTTPNotFound
37
37
38 import kallithea.lib.helpers as h
38 from kallithea.controllers.changeset import create_cs_pr_comment, delete_cs_pr_comment
39 from kallithea.controllers.changeset import create_cs_pr_comment, delete_cs_pr_comment
39 from kallithea.lib import auth, diffs
40 from kallithea.lib import auth, diffs, webutils
40 from kallithea.lib import helpers as h
41 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
41 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
42 from kallithea.lib.base import BaseRepoController, jsonify, render
42 from kallithea.lib.base import BaseRepoController, jsonify, render
43 from kallithea.lib.graphmod import graph_data
43 from kallithea.lib.graphmod import graph_data
@@ -63,7 +63,7 b' def _get_reviewer(user_id):'
63 user = None
63 user = None
64
64
65 if user is None or user.is_default_user:
65 if user is None or user.is_default_user:
66 h.flash(_('Invalid reviewer "%s" specified') % user_id, category='error')
66 webutils.flash(_('Invalid reviewer "%s" specified') % user_id, category='error')
67 raise HTTPBadRequest()
67 raise HTTPBadRequest()
68
68
69 return user
69 return user
@@ -245,7 +245,7 b' class PullrequestsController(BaseRepoCon'
245 try:
245 try:
246 org_scm_instance.get_changeset()
246 org_scm_instance.get_changeset()
247 except EmptyRepositoryError as e:
247 except EmptyRepositoryError as e:
248 h.flash(_('There are no changesets yet'),
248 webutils.flash(_('There are no changesets yet'),
249 category='warning')
249 category='warning')
250 raise HTTPFound(location=url('summary_home', repo_name=org_repo.repo_name))
250 raise HTTPFound(location=url('summary_home', repo_name=org_repo.repo_name))
251
251
@@ -314,7 +314,7 b' class PullrequestsController(BaseRepoCon'
314 log.error(traceback.format_exc())
314 log.error(traceback.format_exc())
315 log.error(str(errors))
315 log.error(str(errors))
316 msg = _('Error creating pull request: %s') % errors.msg
316 msg = _('Error creating pull request: %s') % errors.msg
317 h.flash(msg, 'error')
317 webutils.flash(msg, 'error')
318 raise HTTPBadRequest
318 raise HTTPBadRequest
319
319
320 # heads up: org and other might seem backward here ...
320 # heads up: org and other might seem backward here ...
@@ -333,19 +333,19 b' class PullrequestsController(BaseRepoCon'
333 try:
333 try:
334 cmd = CreatePullRequestAction(org_repo, other_repo, org_ref, other_ref, title, description, owner, reviewers)
334 cmd = CreatePullRequestAction(org_repo, other_repo, org_ref, other_ref, title, description, owner, reviewers)
335 except CreatePullRequestAction.ValidationError as e:
335 except CreatePullRequestAction.ValidationError as e:
336 h.flash(e, category='error', logf=log.error)
336 webutils.flash(e, category='error', logf=log.error)
337 raise HTTPNotFound
337 raise HTTPNotFound
338
338
339 try:
339 try:
340 pull_request = cmd.execute()
340 pull_request = cmd.execute()
341 meta.Session().commit()
341 meta.Session().commit()
342 except Exception:
342 except Exception:
343 h.flash(_('Error occurred while creating pull request'),
343 webutils.flash(_('Error occurred while creating pull request'),
344 category='error')
344 category='error')
345 log.error(traceback.format_exc())
345 log.error(traceback.format_exc())
346 raise HTTPFound(location=url('pullrequest_home', repo_name=repo_name))
346 raise HTTPFound(location=url('pullrequest_home', repo_name=repo_name))
347
347
348 h.flash(_('Successfully opened new pull request'),
348 webutils.flash(_('Successfully opened new pull request'),
349 category='success')
349 category='success')
350 raise HTTPFound(location=pull_request.url())
350 raise HTTPFound(location=pull_request.url())
351
351
@@ -356,19 +356,19 b' class PullrequestsController(BaseRepoCon'
356 try:
356 try:
357 cmd = CreatePullRequestIterationAction(old_pull_request, new_org_rev, new_other_rev, title, description, owner, reviewers)
357 cmd = CreatePullRequestIterationAction(old_pull_request, new_org_rev, new_other_rev, title, description, owner, reviewers)
358 except CreatePullRequestAction.ValidationError as e:
358 except CreatePullRequestAction.ValidationError as e:
359 h.flash(e, category='error', logf=log.error)
359 webutils.flash(e, category='error', logf=log.error)
360 raise HTTPNotFound
360 raise HTTPNotFound
361
361
362 try:
362 try:
363 pull_request = cmd.execute()
363 pull_request = cmd.execute()
364 meta.Session().commit()
364 meta.Session().commit()
365 except Exception:
365 except Exception:
366 h.flash(_('Error occurred while creating pull request'),
366 webutils.flash(_('Error occurred while creating pull request'),
367 category='error')
367 category='error')
368 log.error(traceback.format_exc())
368 log.error(traceback.format_exc())
369 raise HTTPFound(location=old_pull_request.url())
369 raise HTTPFound(location=old_pull_request.url())
370
370
371 h.flash(_('New pull request iteration created'),
371 webutils.flash(_('New pull request iteration created'),
372 category='success')
372 category='success')
373 raise HTTPFound(location=pull_request.url())
373 raise HTTPFound(location=pull_request.url())
374
374
@@ -396,11 +396,11 b' class PullrequestsController(BaseRepoCon'
396 other_removed = old_reviewers - cur_reviewers
396 other_removed = old_reviewers - cur_reviewers
397
397
398 if other_added:
398 if other_added:
399 h.flash(_('Meanwhile, the following reviewers have been added: %s') %
399 webutils.flash(_('Meanwhile, the following reviewers have been added: %s') %
400 (', '.join(u.username for u in other_added)),
400 (', '.join(u.username for u in other_added)),
401 category='warning')
401 category='warning')
402 if other_removed:
402 if other_removed:
403 h.flash(_('Meanwhile, the following reviewers have been removed: %s') %
403 webutils.flash(_('Meanwhile, the following reviewers have been removed: %s') %
404 (', '.join(u.username for u in other_removed)),
404 (', '.join(u.username for u in other_removed)),
405 category='warning')
405 category='warning')
406
406
@@ -425,7 +425,7 b' class PullrequestsController(BaseRepoCon'
425 PullRequestModel().remove_reviewers(user, pull_request, removed_reviewers)
425 PullRequestModel().remove_reviewers(user, pull_request, removed_reviewers)
426
426
427 meta.Session().commit()
427 meta.Session().commit()
428 h.flash(_('Pull request updated'), category='success')
428 webutils.flash(_('Pull request updated'), category='success')
429
429
430 raise HTTPFound(location=pull_request.url())
430 raise HTTPFound(location=pull_request.url())
431
431
@@ -438,7 +438,7 b' class PullrequestsController(BaseRepoCon'
438 if pull_request.owner_id == request.authuser.user_id:
438 if pull_request.owner_id == request.authuser.user_id:
439 PullRequestModel().delete(pull_request)
439 PullRequestModel().delete(pull_request)
440 meta.Session().commit()
440 meta.Session().commit()
441 h.flash(_('Successfully deleted pull request'),
441 webutils.flash(_('Successfully deleted pull request'),
442 category='success')
442 category='success')
443 raise HTTPFound(location=url('my_pullrequests'))
443 raise HTTPFound(location=url('my_pullrequests'))
444 raise HTTPForbidden()
444 raise HTTPForbidden()
@@ -474,7 +474,7 b' class PullrequestsController(BaseRepoCon'
474 c.cs_ranges.append(org_scm_instance.get_changeset(x))
474 c.cs_ranges.append(org_scm_instance.get_changeset(x))
475 except ChangesetDoesNotExistError:
475 except ChangesetDoesNotExistError:
476 c.cs_ranges = []
476 c.cs_ranges = []
477 h.flash(_('Revision %s not found in %s') % (x, c.cs_repo.repo_name),
477 webutils.flash(_('Revision %s not found in %s') % (x, c.cs_repo.repo_name),
478 'error')
478 'error')
479 break
479 break
480 c.cs_ranges_org = None # not stored and not important and moving target - could be calculated ...
480 c.cs_ranges_org = None # not stored and not important and moving target - could be calculated ...
@@ -38,8 +38,7 b' from tg import tmpl_context as c'
38 from tg.i18n import ugettext as _
38 from tg.i18n import ugettext as _
39 from webob.exc import HTTPBadRequest
39 from webob.exc import HTTPBadRequest
40
40
41 import kallithea.lib.helpers as h
41 from kallithea.lib import ext_json, webutils
42 from kallithea.lib import ext_json
43 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
42 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
44 from kallithea.lib.base import BaseRepoController, jsonify, render
43 from kallithea.lib.base import BaseRepoController, jsonify, render
45 from kallithea.lib.celerylib.tasks import get_commits_stats
44 from kallithea.lib.celerylib.tasks import get_commits_stats
@@ -108,7 +107,7 b' class SummaryController(BaseRepoControll'
108 try:
107 try:
109 collection = c.db_repo_scm_instance.get_changesets(reverse=True)
108 collection = c.db_repo_scm_instance.get_changesets(reverse=True)
110 except EmptyRepositoryError as e:
109 except EmptyRepositoryError as e:
111 h.flash(e, category='warning')
110 webutils.flash(e, category='warning')
112 collection = []
111 collection = []
113 c.cs_pagination = Page(collection, page=p, items_per_page=size)
112 c.cs_pagination = Page(collection, page=p, items_per_page=size)
114 page_revisions = [x.raw_id for x in list(c.cs_pagination)]
113 page_revisions = [x.raw_id for x in list(c.cs_pagination)]
@@ -40,6 +40,7 b' from tg.i18n import ugettext as _'
40 from webob.exc import HTTPForbidden, HTTPFound
40 from webob.exc import HTTPForbidden, HTTPFound
41
41
42 import kallithea
42 import kallithea
43 from kallithea.lib import webutils
43 from kallithea.lib.utils import get_repo_group_slug, get_repo_slug, get_user_group_slug
44 from kallithea.lib.utils import get_repo_group_slug, get_repo_slug, get_user_group_slug
44 from kallithea.lib.utils2 import ascii_bytes, ascii_str, safe_bytes
45 from kallithea.lib.utils2 import ascii_bytes, ascii_str, safe_bytes
45 from kallithea.lib.vcs.utils.lazy import LazyProperty
46 from kallithea.lib.vcs.utils.lazy import LazyProperty
@@ -544,9 +545,8 b' def _redirect_to_login(message=None):'
544 """Return an exception that must be raised. It will redirect to the login
545 """Return an exception that must be raised. It will redirect to the login
545 page which will redirect back to the current URL after authentication.
546 page which will redirect back to the current URL after authentication.
546 The optional message will be shown in a flash message."""
547 The optional message will be shown in a flash message."""
547 from kallithea.lib import helpers as h
548 if message:
548 if message:
549 h.flash(message, category='warning')
549 webutils.flash(message, category='warning')
550 p = request.path_qs
550 p = request.path_qs
551 log.debug('Redirecting to login page, origin: %s', p)
551 log.debug('Redirecting to login page, origin: %s', p)
552 return HTTPFound(location=url('login_home', came_from=p))
552 return HTTPFound(location=url('login_home', came_from=p))
@@ -44,7 +44,7 b' from tg import tmpl_context as c'
44 from tg.i18n import ugettext as _
44 from tg.i18n import ugettext as _
45
45
46 import kallithea
46 import kallithea
47 from kallithea.lib import auth_modules, ext_json
47 from kallithea.lib import auth_modules, ext_json, webutils
48 from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware
48 from kallithea.lib.auth import AuthUser, HasPermissionAnyMiddleware
49 from kallithea.lib.exceptions import UserCreationError
49 from kallithea.lib.exceptions import UserCreationError
50 from kallithea.lib.utils import get_repo_slug, is_valid_repo
50 from kallithea.lib.utils import get_repo_slug, is_valid_repo
@@ -361,9 +361,8 b' class BaseController(TGController):'
361 # guaranteed to be side effect free. In practice, the only situation
361 # guaranteed to be side effect free. In practice, the only situation
362 # where we allow side effects without ambient authority is when the
362 # where we allow side effects without ambient authority is when the
363 # authority comes from an API key; and that is handled above.
363 # authority comes from an API key; and that is handled above.
364 from kallithea.lib import helpers as h
364 token = request.POST.get(webutils.session_csrf_secret_name)
365 token = request.POST.get(h.session_csrf_secret_name)
365 if not token or token != webutils.session_csrf_secret_token():
366 if not token or token != h.session_csrf_secret_token():
367 log.error('CSRF check failed')
366 log.error('CSRF check failed')
368 raise webob.exc.HTTPForbidden()
367 raise webob.exc.HTTPForbidden()
369
368
@@ -444,8 +443,7 b' class BaseController(TGController):'
444 try:
443 try:
445 user_info = auth_modules.authenticate('', '', request.environ)
444 user_info = auth_modules.authenticate('', '', request.environ)
446 except UserCreationError as e:
445 except UserCreationError as e:
447 from kallithea.lib import helpers as h
446 webutils.flash(e, 'error', logf=log.error)
448 h.flash(e, 'error', logf=log.error)
449 else:
447 else:
450 if user_info is not None:
448 if user_info is not None:
451 username = user_info['username']
449 username = user_info['username']
@@ -474,12 +472,11 b' class BaseController(TGController):'
474 raise webob.exc.HTTPMethodNotAllowed()
472 raise webob.exc.HTTPMethodNotAllowed()
475
473
476 # Make sure CSRF token never appears in the URL. If so, invalidate it.
474 # Make sure CSRF token never appears in the URL. If so, invalidate it.
477 from kallithea.lib import helpers as h
475 if webutils.session_csrf_secret_name in request.GET:
478 if h.session_csrf_secret_name in request.GET:
479 log.error('CSRF key leak detected')
476 log.error('CSRF key leak detected')
480 session.pop(h.session_csrf_secret_name, None)
477 session.pop(webutils.session_csrf_secret_name, None)
481 session.save()
478 session.save()
482 h.flash(_('CSRF token leak has been detected - all form tokens have been expired'),
479 webutils.flash(_('CSRF token leak has been detected - all form tokens have been expired'),
483 category='error')
480 category='error')
484
481
485 # WebOb already ignores request payload parameters for anything other
482 # WebOb already ignores request payload parameters for anything other
@@ -575,8 +572,7 b' class BaseRepoController(BaseController)'
575 if c.db_repo_scm_instance is None:
572 if c.db_repo_scm_instance is None:
576 log.error('%s this repository is present in database but it '
573 log.error('%s this repository is present in database but it '
577 'cannot be created as an scm instance', c.repo_name)
574 'cannot be created as an scm instance', c.repo_name)
578 from kallithea.lib import helpers as h
575 webutils.flash(_('Repository not found in the filesystem'),
579 h.flash(_('Repository not found in the filesystem'),
580 category='error')
576 category='error')
581 raise webob.exc.HTTPNotFound()
577 raise webob.exc.HTTPNotFound()
582
578
@@ -592,22 +588,21 b' class BaseRepoController(BaseController)'
592 """
588 """
593 Safe way to get changeset. If error occurs show error.
589 Safe way to get changeset. If error occurs show error.
594 """
590 """
595 from kallithea.lib import helpers as h
596 try:
591 try:
597 return repo.scm_instance.get_ref_revision(ref_type, ref_name)
592 return repo.scm_instance.get_ref_revision(ref_type, ref_name)
598 except EmptyRepositoryError as e:
593 except EmptyRepositoryError as e:
599 if returnempty:
594 if returnempty:
600 return repo.scm_instance.EMPTY_CHANGESET
595 return repo.scm_instance.EMPTY_CHANGESET
601 h.flash(_('There are no changesets yet'), category='error')
596 webutils.flash(_('There are no changesets yet'), category='error')
602 raise webob.exc.HTTPNotFound()
597 raise webob.exc.HTTPNotFound()
603 except ChangesetDoesNotExistError as e:
598 except ChangesetDoesNotExistError as e:
604 h.flash(_('Changeset for %s %s not found in %s') %
599 webutils.flash(_('Changeset for %s %s not found in %s') %
605 (ref_type, ref_name, repo.repo_name),
600 (ref_type, ref_name, repo.repo_name),
606 category='error')
601 category='error')
607 raise webob.exc.HTTPNotFound()
602 raise webob.exc.HTTPNotFound()
608 except RepositoryError as e:
603 except RepositoryError as e:
609 log.error(traceback.format_exc())
604 log.error(traceback.format_exc())
610 h.flash(e, category='error')
605 webutils.flash(e, category='error')
611 raise webob.exc.HTTPBadRequest()
606 raise webob.exc.HTTPBadRequest()
612
607
613
608
@@ -642,7 +637,6 b' def IfSshEnabled(func, *args, **kwargs):'
642 If SSH access is disabled in the configuration file, HTTPNotFound is raised.
637 If SSH access is disabled in the configuration file, HTTPNotFound is raised.
643 """
638 """
644 if not c.ssh_enabled:
639 if not c.ssh_enabled:
645 from kallithea.lib import helpers as h
640 webutils.flash(_("SSH access is disabled."), category='warning')
646 h.flash(_("SSH access is disabled."), category='warning')
647 raise webob.exc.HTTPNotFound()
641 raise webob.exc.HTTPNotFound()
648 return func(*args, **kwargs)
642 return func(*args, **kwargs)
@@ -31,7 +31,7 b' import re'
31
31
32 from tg.i18n import ugettext as _
32 from tg.i18n import ugettext as _
33
33
34 from kallithea.lib import helpers as h
34 from kallithea.lib import webutils
35 from kallithea.lib.utils2 import safe_str
35 from kallithea.lib.utils2 import safe_str
36 from kallithea.lib.vcs.backends.base import EmptyChangeset
36 from kallithea.lib.vcs.backends.base import EmptyChangeset
37 from kallithea.lib.vcs.exceptions import VCSError
37 from kallithea.lib.vcs.exceptions import VCSError
@@ -207,7 +207,7 b' def wrapped_diff(filenode_old, filenode_'
207 if not html_diff:
207 if not html_diff:
208 submodules = [o for o in [filenode_new, filenode_old] if isinstance(o, SubModuleNode)]
208 submodules = [o for o in [filenode_new, filenode_old] if isinstance(o, SubModuleNode)]
209 if submodules:
209 if submodules:
210 html_diff = wrap_to_table(h.escape('Submodule %r' % submodules[0]))
210 html_diff = wrap_to_table(webutils.escape('Submodule %r' % submodules[0]))
211 else:
211 else:
212 html_diff = wrap_to_table(_('No changes detected'))
212 html_diff = wrap_to_table(_('No changes detected'))
213
213
@@ -249,7 +249,7 b' def get_diff(scm_instance, rev1, rev2, p'
249 return scm_instance.get_diff(rev1, rev2, path=path,
249 return scm_instance.get_diff(rev1, rev2, path=path,
250 ignore_whitespace=ignore_whitespace, context=context)
250 ignore_whitespace=ignore_whitespace, context=context)
251 except MemoryError:
251 except MemoryError:
252 h.flash('MemoryError: Diff is too big', category='error')
252 webutils.flash('MemoryError: Diff is too big', category='error')
253 return b''
253 return b''
254
254
255
255
@@ -20,7 +20,6 b' available to Controllers. This module is'
20 import hashlib
20 import hashlib
21 import json
21 import json
22 import logging
22 import logging
23 import random
24 import re
23 import re
25 import textwrap
24 import textwrap
26 import urllib.parse
25 import urllib.parse
@@ -28,16 +27,7 b' import urllib.parse'
28 from beaker.cache import cache_region
27 from beaker.cache import cache_region
29 from pygments import highlight as code_highlight
28 from pygments import highlight as code_highlight
30 from pygments.formatters.html import HtmlFormatter
29 from pygments.formatters.html import HtmlFormatter
31 from tg import session
32 from tg.i18n import ugettext as _
30 from tg.i18n import ugettext as _
33 from webhelpers2.html import HTML, escape, literal
34 from webhelpers2.html.tags import NotGiven, Option, Options, _input, _make_safe_id_component, checkbox, end_form
35 from webhelpers2.html.tags import form as insecure_form
36 from webhelpers2.html.tags import hidden, link_to, password, radio
37 from webhelpers2.html.tags import select as webhelpers2_select
38 from webhelpers2.html.tags import submit, text, textarea
39 from webhelpers2.number import format_byte_size
40 from webhelpers2.text import chop_at, truncate, wrap_paragraphs
41
31
42 import kallithea
32 import kallithea
43 from kallithea.lib.annotate import annotate_highlight
33 from kallithea.lib.annotate import annotate_highlight
@@ -55,47 +45,49 b' from kallithea.lib.vcs.exceptions import'
55 # SCM FILTERS available via h.
45 # SCM FILTERS available via h.
56 #==============================================================================
46 #==============================================================================
57 from kallithea.lib.vcs.utils import author_email, author_name
47 from kallithea.lib.vcs.utils import author_email, author_name
58 from kallithea.lib.webutils import canonical_url, url
48 from kallithea.lib.webutils import (HTML, Option, canonical_url, checkbox, chop_at, end_form, escape, form, format_byte_size, hidden, html_escape, link_to,
49 literal, password, pop_flash_messages, radio, reset, safeid, select, session_csrf_secret_name, session_csrf_secret_token,
50 submit, text, textarea, truncate, url, wrap_paragraphs)
59 from kallithea.model import db
51 from kallithea.model import db
60 from kallithea.model.changeset_status import ChangesetStatusModel
52 from kallithea.model.changeset_status import ChangesetStatusModel
61
53
62
54
63 # mute pyflakes "imported but unused"
55 # mute pyflakes "imported but unused"
56 # from webutils
64 assert Option
57 assert Option
58 assert canonical_url
65 assert checkbox
59 assert checkbox
60 assert chop_at
66 assert end_form
61 assert end_form
62 assert form
63 assert format_byte_size
64 assert hidden
67 assert password
65 assert password
66 assert pop_flash_messages
68 assert radio
67 assert radio
68 assert reset
69 assert safeid
70 assert select
71 assert session_csrf_secret_name
72 assert session_csrf_secret_token
69 assert submit
73 assert submit
70 assert text
74 assert text
71 assert textarea
75 assert textarea
72 assert format_byte_size
73 assert chop_at
74 assert wrap_paragraphs
76 assert wrap_paragraphs
77 # from kallithea.lib.auth
75 assert HasPermissionAny
78 assert HasPermissionAny
76 assert HasRepoGroupPermissionLevel
79 assert HasRepoGroupPermissionLevel
77 assert HasRepoPermissionLevel
80 assert HasRepoPermissionLevel
81 # from utils2
78 assert age
82 assert age
79 assert time_to_datetime
83 assert time_to_datetime
84 # from vcs
80 assert EmptyChangeset
85 assert EmptyChangeset
81 assert canonical_url
82
86
83
87
84 log = logging.getLogger(__name__)
88 log = logging.getLogger(__name__)
85
89
86
90
87 def html_escape(s):
88 """Return string with all html escaped.
89 This is also safe for javascript in html but not necessarily correct.
90 """
91 return (s
92 .replace('&', '&')
93 .replace(">", ">")
94 .replace("<", "&lt;")
95 .replace('"', "&quot;")
96 .replace("'", "&apos;") # Note: this is HTML5 not HTML4 and might not work in mails
97 )
98
99 def js(value):
91 def js(value):
100 """Convert Python value to the corresponding JavaScript representation.
92 """Convert Python value to the corresponding JavaScript representation.
101
93
@@ -152,44 +144,6 b' def shorter(s, size=20, firstline=False,'
152 return s
144 return s
153
145
154
146
155 def reset(name, value, id=NotGiven, **attrs):
156 """Create a reset button, similar to webhelpers2.html.tags.submit ."""
157 return _input("reset", name, value, id, attrs)
158
159
160 def select(name, selected_values, options, id=NotGiven, **attrs):
161 """Convenient wrapper of webhelpers2 to let it accept options as a tuple list"""
162 if isinstance(options, list):
163 option_list = options
164 # Handle old value,label lists ... where value also can be value,label lists
165 options = Options()
166 for x in option_list:
167 if isinstance(x, tuple) and len(x) == 2:
168 value, label = x
169 elif isinstance(x, str):
170 value = label = x
171 else:
172 log.error('invalid select option %r', x)
173 raise
174 if isinstance(value, list):
175 og = options.add_optgroup(label)
176 for x in value:
177 if isinstance(x, tuple) and len(x) == 2:
178 group_value, group_label = x
179 elif isinstance(x, str):
180 group_value = group_label = x
181 else:
182 log.error('invalid select option %r', x)
183 raise
184 og.add_option(group_label, group_value)
185 else:
186 options.add_option(label, value)
187 return webhelpers2_select(name, selected_values, options, id=id, **attrs)
188
189
190 safeid = _make_safe_id_component
191
192
193 def FID(raw_id, path):
147 def FID(raw_id, path):
194 """
148 """
195 Creates a unique ID for filenode based on it's hash of path and revision
149 Creates a unique ID for filenode based on it's hash of path and revision
@@ -448,76 +402,6 b' def pygmentize_annotation(repo_name, fil'
448 return literal(markup_whitespace(annotate_highlight(filenode, url_func, **kwargs)))
402 return literal(markup_whitespace(annotate_highlight(filenode, url_func, **kwargs)))
449
403
450
404
451 class _Message(object):
452 """A message returned by ``pop_flash_messages()``.
453
454 Converting the message to a string returns the message text. Instances
455 also have the following attributes:
456
457 * ``category``: the category specified when the message was created.
458 * ``message``: the html-safe message text.
459 """
460
461 def __init__(self, category, message):
462 self.category = category
463 self.message = message
464
465
466 def _session_flash_messages(append=None, clear=False):
467 """Manage a message queue in tg.session: return the current message queue
468 after appending the given message, and possibly clearing the queue."""
469 key = 'flash'
470 if key in session:
471 flash_messages = session[key]
472 else:
473 if append is None: # common fast path - also used for clearing empty queue
474 return [] # don't bother saving
475 flash_messages = []
476 session[key] = flash_messages
477 if append is not None and append not in flash_messages:
478 flash_messages.append(append)
479 if clear:
480 session.pop(key, None)
481 session.save()
482 return flash_messages
483
484
485 def flash(message, category, logf=None):
486 """
487 Show a message to the user _and_ log it through the specified function
488
489 category: notice (default), warning, error, success
490 logf: a custom log function - such as log.debug
491
492 logf defaults to log.info, unless category equals 'success', in which
493 case logf defaults to log.debug.
494 """
495 assert category in ('error', 'success', 'warning'), category
496 if hasattr(message, '__html__'):
497 # render to HTML for storing in cookie
498 safe_message = str(message)
499 else:
500 # Apply str - the message might be an exception with __str__
501 # Escape, so we can trust the result without further escaping, without any risk of injection
502 safe_message = html_escape(str(message))
503 if logf is None:
504 logf = log.info
505 if category == 'success':
506 logf = log.debug
507
508 logf('Flash %s: %s', category, safe_message)
509
510 _session_flash_messages(append=(category, safe_message))
511
512
513 def pop_flash_messages():
514 """Return all accumulated messages and delete them from the session.
515
516 The return value is a list of ``Message`` objects.
517 """
518 return [_Message(category, message) for category, message in _session_flash_messages(clear=True)]
519
520
521 def capitalize(x):
405 def capitalize(x):
522 return x.capitalize()
406 return x.capitalize()
523
407
@@ -1317,23 +1201,3 b' def journal_filter_help():'
1317 def ip_range(ip_addr):
1201 def ip_range(ip_addr):
1318 s, e = db.UserIpMap._get_ip_range(ip_addr)
1202 s, e = db.UserIpMap._get_ip_range(ip_addr)
1319 return '%s - %s' % (s, e)
1203 return '%s - %s' % (s, e)
1320
1321
1322 session_csrf_secret_name = "_session_csrf_secret_token"
1323
1324 def session_csrf_secret_token():
1325 """Return (and create) the current session's CSRF protection token."""
1326 if not session_csrf_secret_name in session:
1327 session[session_csrf_secret_name] = str(random.getrandbits(128))
1328 session.save()
1329 return session[session_csrf_secret_name]
1330
1331 def form(url, method="post", **attrs):
1332 """Like webhelpers.html.tags.form , but automatically adding
1333 session_csrf_secret_token for POST. The secret is thus never leaked in GET
1334 URLs.
1335 """
1336 form = insecure_form(url, method, **attrs)
1337 if method.lower() == 'get':
1338 return form
1339 return form + HTML.div(hidden(session_csrf_secret_name, session_csrf_secret_token()), style="display: none;")
@@ -32,7 +32,7 b' import time'
32 import mercurial.scmutil
32 import mercurial.scmutil
33
33
34 import kallithea
34 import kallithea
35 from kallithea.lib import helpers as h
35 from kallithea.lib import webutils
36 from kallithea.lib.exceptions import UserCreationError
36 from kallithea.lib.exceptions import UserCreationError
37 from kallithea.lib.utils import action_logger, make_ui
37 from kallithea.lib.utils import action_logger, make_ui
38 from kallithea.lib.utils2 import HookEnvironmentError, ascii_str, get_hook_environment, safe_bytes, safe_str
38 from kallithea.lib.utils2 import HookEnvironmentError, ascii_str, get_hook_environment, safe_bytes, safe_str
@@ -59,9 +59,9 b' def _get_scm_size(alias, root_path):'
59 except OSError:
59 except OSError:
60 pass
60 pass
61
61
62 size_scm_f = h.format_byte_size(size_scm)
62 size_scm_f = webutils.format_byte_size(size_scm)
63 size_root_f = h.format_byte_size(size_root)
63 size_root_f = webutils.format_byte_size(size_root)
64 size_total_f = h.format_byte_size(size_root + size_scm)
64 size_total_f = webutils.format_byte_size(size_root + size_scm)
65
65
66 return size_scm_f, size_root_f, size_total_f
66 return size_scm_f, size_root_f, size_total_f
67
67
@@ -19,9 +19,8 b' import logging'
19 import paginate
19 import paginate
20 import paginate_sqlalchemy
20 import paginate_sqlalchemy
21 import sqlalchemy.orm
21 import sqlalchemy.orm
22 from webhelpers2.html import literal
23
22
24 from kallithea.lib.webutils import url
23 from kallithea.lib import webutils
25
24
26
25
27 log = logging.getLogger(__name__)
26 log = logging.getLogger(__name__)
@@ -35,10 +34,10 b' class Page(paginate.Page):'
35 if isinstance(collection, sqlalchemy.orm.query.Query):
34 if isinstance(collection, sqlalchemy.orm.query.Query):
36 collection = paginate_sqlalchemy.SqlalchemyOrmWrapper(collection)
35 collection = paginate_sqlalchemy.SqlalchemyOrmWrapper(collection)
37 paginate.Page.__init__(self, collection, page=page, items_per_page=items_per_page, item_count=item_count,
36 paginate.Page.__init__(self, collection, page=page, items_per_page=items_per_page, item_count=item_count,
38 url_maker=lambda page: url.current(page=page, **kwargs))
37 url_maker=lambda page: webutils.url.current(page=page, **kwargs))
39
38
40 def pager(self):
39 def pager(self):
41 return literal(
40 return webutils.literal(
42 paginate.Page.pager(self,
41 paginate.Page.pager(self,
43 format='<ul class="pagination">$link_previous\n~4~$link_next</ul>',
42 format='<ul class="pagination">$link_previous\n~4~$link_next</ul>',
44 link_attr={'class': 'pager_link'},
43 link_attr={'class': 'pager_link'},
@@ -20,11 +20,46 b' thread-local "global" variables. It shou'
20 imported anywhere - just like the global variables can be used everywhere.
20 imported anywhere - just like the global variables can be used everywhere.
21 """
21 """
22
22
23 from tg import request
23 import logging
24 import random
25
26 from tg import request, session
27 from webhelpers2.html import HTML, escape, literal
28 from webhelpers2.html.tags import NotGiven, Option, Options, _input
29 from webhelpers2.html.tags import _make_safe_id_component as safeid
30 from webhelpers2.html.tags import checkbox, end_form
31 from webhelpers2.html.tags import form as insecure_form
32 from webhelpers2.html.tags import hidden, link_to, password, radio
33 from webhelpers2.html.tags import select as webhelpers2_select
34 from webhelpers2.html.tags import submit, text, textarea
35 from webhelpers2.number import format_byte_size
36 from webhelpers2.text import chop_at, truncate, wrap_paragraphs
24
37
25 import kallithea
38 import kallithea
26
39
27
40
41 log = logging.getLogger(__name__)
42
43
44 # mute pyflakes "imported but unused"
45 assert Option
46 assert checkbox
47 assert chop_at
48 assert end_form
49 assert escape
50 assert format_byte_size
51 assert link_to
52 assert literal
53 assert password
54 assert radio
55 assert safeid
56 assert submit
57 assert text
58 assert textarea
59 assert truncate
60 assert wrap_paragraphs
61
62
28 #
63 #
29 # General Kallithea URL handling
64 # General Kallithea URL handling
30 #
65 #
@@ -75,3 +110,149 b' def canonical_hostname():'
75 except IndexError:
110 except IndexError:
76 parts = url('home', qualified=True).split('://', 1)
111 parts = url('home', qualified=True).split('://', 1)
77 return parts[1].split('/', 1)[0]
112 return parts[1].split('/', 1)[0]
113
114
115 #
116 # Custom Webhelpers2 stuff
117 #
118
119 def html_escape(s):
120 """Return string with all html escaped.
121 This is also safe for javascript in html but not necessarily correct.
122 """
123 return (s
124 .replace('&', '&amp;')
125 .replace(">", "&gt;")
126 .replace("<", "&lt;")
127 .replace('"', "&quot;")
128 .replace("'", "&apos;") # Note: this is HTML5 not HTML4 and might not work in mails
129 )
130
131
132 def reset(name, value, id=NotGiven, **attrs):
133 """Create a reset button, similar to webhelpers2.html.tags.submit ."""
134 return _input("reset", name, value, id, attrs)
135
136
137 def select(name, selected_values, options, id=NotGiven, **attrs):
138 """Convenient wrapper of webhelpers2 to let it accept options as a tuple list"""
139 if isinstance(options, list):
140 option_list = options
141 # Handle old value,label lists ... where value also can be value,label lists
142 options = Options()
143 for x in option_list:
144 if isinstance(x, tuple) and len(x) == 2:
145 value, label = x
146 elif isinstance(x, str):
147 value = label = x
148 else:
149 log.error('invalid select option %r', x)
150 raise
151 if isinstance(value, list):
152 og = options.add_optgroup(label)
153 for x in value:
154 if isinstance(x, tuple) and len(x) == 2:
155 group_value, group_label = x
156 elif isinstance(x, str):
157 group_value = group_label = x
158 else:
159 log.error('invalid select option %r', x)
160 raise
161 og.add_option(group_label, group_value)
162 else:
163 options.add_option(label, value)
164 return webhelpers2_select(name, selected_values, options, id=id, **attrs)
165
166
167 session_csrf_secret_name = "_session_csrf_secret_token"
168
169 def session_csrf_secret_token():
170 """Return (and create) the current session's CSRF protection token."""
171 if not session_csrf_secret_name in session:
172 session[session_csrf_secret_name] = str(random.getrandbits(128))
173 session.save()
174 return session[session_csrf_secret_name]
175
176 def form(url, method="post", **attrs):
177 """Like webhelpers.html.tags.form , but automatically adding
178 session_csrf_secret_token for POST. The secret is thus never leaked in GET
179 URLs.
180 """
181 form = insecure_form(url, method, **attrs)
182 if method.lower() == 'get':
183 return form
184 return form + HTML.div(hidden(session_csrf_secret_name, session_csrf_secret_token()), style="display: none;")
185
186
187 #
188 # Flash messages, stored in cookie
189 #
190
191 class _Message(object):
192 """A message returned by ``pop_flash_messages()``.
193
194 Converting the message to a string returns the message text. Instances
195 also have the following attributes:
196
197 * ``category``: the category specified when the message was created.
198 * ``message``: the html-safe message text.
199 """
200
201 def __init__(self, category, message):
202 self.category = category
203 self.message = message
204
205
206 def _session_flash_messages(append=None, clear=False):
207 """Manage a message queue in tg.session: return the current message queue
208 after appending the given message, and possibly clearing the queue."""
209 key = 'flash'
210 if key in session:
211 flash_messages = session[key]
212 else:
213 if append is None: # common fast path - also used for clearing empty queue
214 return [] # don't bother saving
215 flash_messages = []
216 session[key] = flash_messages
217 if append is not None and append not in flash_messages:
218 flash_messages.append(append)
219 if clear:
220 session.pop(key, None)
221 session.save()
222 return flash_messages
223
224
225 def flash(message, category, logf=None):
226 """
227 Show a message to the user _and_ log it through the specified function
228
229 category: notice (default), warning, error, success
230 logf: a custom log function - such as log.debug
231
232 logf defaults to log.info, unless category equals 'success', in which
233 case logf defaults to log.debug.
234 """
235 assert category in ('error', 'success', 'warning'), category
236 if hasattr(message, '__html__'):
237 # render to HTML for storing in cookie
238 safe_message = str(message)
239 else:
240 # Apply str - the message might be an exception with __str__
241 # Escape, so we can trust the result without further escaping, without any risk of injection
242 safe_message = html_escape(str(message))
243 if logf is None:
244 logf = log.info
245 if category == 'success':
246 logf = log.debug
247
248 logf('Flash %s: %s', category, safe_message)
249
250 _session_flash_messages(append=(category, safe_message))
251
252
253 def pop_flash_messages():
254 """Return all accumulated messages and delete them from the session.
255
256 The return value is a list of ``Message`` objects.
257 """
258 return [_Message(category, message) for category, message in _session_flash_messages(clear=True)]
@@ -81,7 +81,7 b' class ChangesetCommentsModel(object):'
81 repo_name=repo.repo_name,
81 repo_name=repo.repo_name,
82 revision=revision,
82 revision=revision,
83 anchor='comment-%s' % comment.comment_id)
83 anchor='comment-%s' % comment.comment_id)
84 subj = h.link_to(
84 subj = webutils.link_to(
85 'Re changeset: %(desc)s %(line)s' %
85 'Re changeset: %(desc)s %(line)s' %
86 {'desc': desc, 'line': line},
86 {'desc': desc, 'line': line},
87 comment_url)
87 comment_url)
@@ -127,7 +127,7 b' class ChangesetCommentsModel(object):'
127 webutils.canonical_hostname()))
127 webutils.canonical_hostname()))
128 comment_url = pull_request.url(canonical=True,
128 comment_url = pull_request.url(canonical=True,
129 anchor='comment-%s' % comment.comment_id)
129 anchor='comment-%s' % comment.comment_id)
130 subj = h.link_to(
130 subj = webutils.link_to(
131 'Re pull request %(pr_nice_id)s: %(desc)s %(line)s' %
131 'Re pull request %(pr_nice_id)s: %(desc)s %(line)s' %
132 {'desc': desc,
132 {'desc': desc,
133 'pr_nice_id': comment.pull_request.nice_id(),
133 'pr_nice_id': comment.pull_request.nice_id(),
@@ -1306,9 +1306,8 b' class Repository(meta.Base, BaseDbModel)'
1306 return grouped
1306 return grouped
1307
1307
1308 def _repo_size(self):
1308 def _repo_size(self):
1309 from kallithea.lib import helpers as h
1310 log.debug('calculating repository size...')
1309 log.debug('calculating repository size...')
1311 return h.format_byte_size(self.scm_instance.size)
1310 return webutils.format_byte_size(self.scm_instance.size)
1312
1311
1313 #==========================================================================
1312 #==========================================================================
1314 # SCM CACHE INSTANCE
1313 # SCM CACHE INSTANCE
@@ -1397,10 +1396,9 b' class RepoGroup(meta.Base, BaseDbModel):'
1397 @classmethod
1396 @classmethod
1398 def _generate_choice(cls, repo_group):
1397 def _generate_choice(cls, repo_group):
1399 """Return tuple with group_id and name as html literal"""
1398 """Return tuple with group_id and name as html literal"""
1400 from webhelpers2.html import literal
1401 if repo_group is None:
1399 if repo_group is None:
1402 return (-1, '-- %s --' % _('top level'))
1400 return (-1, '-- %s --' % _('top level'))
1403 return repo_group.group_id, literal(cls.SEP.join(repo_group.full_path_splitted))
1401 return repo_group.group_id, webutils.literal(cls.SEP.join(repo_group.full_path_splitted))
1404
1402
1405 @classmethod
1403 @classmethod
1406 def groups_choices(cls, groups):
1404 def groups_choices(cls, groups):
@@ -82,7 +82,7 b' class PullRequestModel(object):'
82 threading = ['%s-pr-%s@%s' % (pr.other_repo.repo_name,
82 threading = ['%s-pr-%s@%s' % (pr.other_repo.repo_name,
83 pr.pull_request_id,
83 pr.pull_request_id,
84 webutils.canonical_hostname())]
84 webutils.canonical_hostname())]
85 subject = h.link_to(
85 subject = webutils.link_to(
86 _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') %
86 _('%(user)s wants you to review pull request %(pr_nice_id)s: %(pr_title)s') %
87 {'user': user.username,
87 {'user': user.username,
88 'pr_title': pr.title,
88 'pr_title': pr.title,
@@ -314,7 +314,6 b' class UserModel(object):'
314 allowing users to copy-paste or manually enter the token from the
314 allowing users to copy-paste or manually enter the token from the
315 email.
315 email.
316 """
316 """
317 import kallithea.lib.helpers as h
318 from kallithea.lib.celerylib import tasks
317 from kallithea.lib.celerylib import tasks
319 from kallithea.model.notification import EmailNotificationModel
318 from kallithea.model.notification import EmailNotificationModel
320
319
@@ -326,7 +325,7 b' class UserModel(object):'
326 log.debug('password reset user %s found', user)
325 log.debug('password reset user %s found', user)
327 token = self.get_reset_password_token(user,
326 token = self.get_reset_password_token(user,
328 timestamp,
327 timestamp,
329 h.session_csrf_secret_token())
328 webutils.session_csrf_secret_token())
330 # URL must be fully qualified; but since the token is locked to
329 # URL must be fully qualified; but since the token is locked to
331 # the current browser session, we must provide a URL with the
330 # the current browser session, we must provide a URL with the
332 # current scheme and hostname, rather than the canonical_url.
331 # current scheme and hostname, rather than the canonical_url.
@@ -359,7 +358,6 b' class UserModel(object):'
359 timestamp=timestamp)
358 timestamp=timestamp)
360
359
361 def verify_reset_password_token(self, email, timestamp, token):
360 def verify_reset_password_token(self, email, timestamp, token):
362 import kallithea.lib.helpers as h
363 user = db.User.get_by_email(email)
361 user = db.User.get_by_email(email)
364 if user is None:
362 if user is None:
365 log.debug("user with email %s not found", email)
363 log.debug("user with email %s not found", email)
@@ -377,7 +375,7 b' class UserModel(object):'
377
375
378 expected_token = self.get_reset_password_token(user,
376 expected_token = self.get_reset_password_token(user,
379 timestamp,
377 timestamp,
380 h.session_csrf_secret_token())
378 webutils.session_csrf_secret_token())
381 log.debug('computed password reset token: %s', expected_token)
379 log.debug('computed password reset token: %s', expected_token)
382 log.debug('received password reset token: %s', token)
380 log.debug('received password reset token: %s', token)
383 return expected_token == token
381 return expected_token == token
@@ -19,7 +19,7 b' from webob.exc import HTTPNotFound'
19
19
20 import kallithea
20 import kallithea
21 from kallithea.controllers.admin.users import UsersController
21 from kallithea.controllers.admin.users import UsersController
22 from kallithea.lib import helpers as h
22 from kallithea.lib import webutils
23 from kallithea.lib.auth import check_password
23 from kallithea.lib.auth import check_password
24 from kallithea.model import db, meta, validators
24 from kallithea.model import db, meta, validators
25 from kallithea.model.user import UserModel
25 from kallithea.model.user import UserModel
@@ -112,7 +112,7 b' class TestAdminUsersController(base.Test'
112
112
113 with test_context(self.app):
113 with test_context(self.app):
114 msg = validators.ValidUsername(False, {})._messages['system_invalid_username']
114 msg = validators.ValidUsername(False, {})._messages['system_invalid_username']
115 msg = h.html_escape(msg % {'username': 'new_user'})
115 msg = webutils.html_escape(msg % {'username': 'new_user'})
116 response.mustcontain("""<span class="error-message">%s</span>""" % msg)
116 response.mustcontain("""<span class="error-message">%s</span>""" % msg)
117 response.mustcontain("""<span class="error-message">Please enter a value</span>""")
117 response.mustcontain("""<span class="error-message">Please enter a value</span>""")
118 response.mustcontain("""<span class="error-message">An email address must contain a single @</span>""")
118 response.mustcontain("""<span class="error-message">An email address must contain a single @</span>""")
@@ -569,7 +569,7 b' class TestAdminUsersController_unittest('
569 # flash complains about an non-existing session
569 # flash complains about an non-existing session
570 def flash_mock(*args, **kwargs):
570 def flash_mock(*args, **kwargs):
571 pass
571 pass
572 monkeypatch.setattr(h, 'flash', flash_mock)
572 monkeypatch.setattr(webutils, 'flash', flash_mock)
573
573
574 u = UsersController()
574 u = UsersController()
575 # a regular user should work correctly
575 # a regular user should work correctly
@@ -7,7 +7,7 b' import mock'
7 from tg.util.webtest import test_context
7 from tg.util.webtest import test_context
8
8
9 import kallithea.lib.celerylib.tasks
9 import kallithea.lib.celerylib.tasks
10 from kallithea.lib import helpers as h
10 from kallithea.lib import webutils
11 from kallithea.lib.auth import check_password
11 from kallithea.lib.auth import check_password
12 from kallithea.lib.utils2 import generate_api_key
12 from kallithea.lib.utils2 import generate_api_key
13 from kallithea.model import db, meta, validators
13 from kallithea.model import db, meta, validators
@@ -238,7 +238,7 b' class TestLoginController(base.TestContr'
238
238
239 with test_context(self.app):
239 with test_context(self.app):
240 msg = validators.ValidUsername()._messages['username_exists']
240 msg = validators.ValidUsername()._messages['username_exists']
241 msg = h.html_escape(msg % {'username': uname})
241 msg = webutils.html_escape(msg % {'username': uname})
242 response.mustcontain(msg)
242 response.mustcontain(msg)
243
243
244 def test_register_err_same_email(self):
244 def test_register_err_same_email(self):
@@ -311,7 +311,7 b' class TestLoginController(base.TestContr'
311 response.mustcontain('An email address must contain a single @')
311 response.mustcontain('An email address must contain a single @')
312 with test_context(self.app):
312 with test_context(self.app):
313 msg = validators.ValidUsername()._messages['username_exists']
313 msg = validators.ValidUsername()._messages['username_exists']
314 msg = h.html_escape(msg % {'username': usr})
314 msg = webutils.html_escape(msg % {'username': usr})
315 response.mustcontain(msg)
315 response.mustcontain(msg)
316
316
317 def test_register_special_chars(self):
317 def test_register_special_chars(self):
@@ -2,7 +2,7 b''
2
2
3 from tg.util.webtest import test_context
3 from tg.util.webtest import test_context
4
4
5 from kallithea.lib import helpers as h
5 from kallithea.lib import webutils
6 from kallithea.model import db, meta
6 from kallithea.model import db, meta
7 from kallithea.model.user import UserModel
7 from kallithea.model.user import UserModel
8 from kallithea.tests import base
8 from kallithea.tests import base
@@ -186,7 +186,7 b' class TestMyAccountController(base.TestC'
186 with test_context(self.app):
186 with test_context(self.app):
187 msg = validators.ValidUsername(edit=False, old_data={}) \
187 msg = validators.ValidUsername(edit=False, old_data={}) \
188 ._messages['username_exists']
188 ._messages['username_exists']
189 msg = h.html_escape(msg % {'username': base.TEST_USER_ADMIN_LOGIN})
189 msg = webutils.html_escape(msg % {'username': base.TEST_USER_ADMIN_LOGIN})
190 response.mustcontain(msg)
190 response.mustcontain(msg)
191
191
192 def test_my_account_api_keys(self):
192 def test_my_account_api_keys(self):
General Comments 0
You need to be logged in to leave comments. Login now