##// END OF EJS Templates
bugfix when form had errors, it was crashing
marcink -
r821:2b5f0e76 beta
parent child Browse files
Show More
@@ -1,290 +1,305 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # repos controller for pylons
3 # repos controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 7, 2010
21 Created on April 7, 2010
22 admin controller for pylons
22 admin controller for pylons
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from formencode import htmlfill
25 from formencode import htmlfill
26 from operator import itemgetter
26 from operator import itemgetter
27 from paste.httpexceptions import HTTPInternalServerError
27 from paste.httpexceptions import HTTPInternalServerError
28 from pylons import request, response, session, tmpl_context as c, url
28 from pylons import request, response, session, tmpl_context as c, url
29 from pylons.controllers.util import abort, redirect
29 from pylons.controllers.util import abort, redirect
30 from pylons.i18n.translation import _
30 from pylons.i18n.translation import _
31 from rhodecode.lib import helpers as h
31 from rhodecode.lib import helpers as h
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
33 HasPermissionAnyDecorator
33 HasPermissionAnyDecorator
34 from rhodecode.lib.base import BaseController, render
34 from rhodecode.lib.base import BaseController, render
35 from rhodecode.lib.utils import invalidate_cache, action_logger
35 from rhodecode.lib.utils import invalidate_cache, action_logger
36 from rhodecode.model.db import User
36 from rhodecode.model.db import User
37 from rhodecode.model.forms import RepoForm
37 from rhodecode.model.forms import RepoForm
38 from rhodecode.model.scm import ScmModel
38 from rhodecode.model.scm import ScmModel
39 from rhodecode.model.repo import RepoModel
39 from rhodecode.model.repo import RepoModel
40 import formencode
40 import formencode
41 import logging
41 import logging
42 import traceback
42 import traceback
43
43
44 log = logging.getLogger(__name__)
44 log = logging.getLogger(__name__)
45
45
46 class ReposController(BaseController):
46 class ReposController(BaseController):
47 """REST Controller styled on the Atom Publishing Protocol"""
47 """REST Controller styled on the Atom Publishing Protocol"""
48 # To properly map this controller, ensure your config/routing.py
48 # To properly map this controller, ensure your config/routing.py
49 # file has a resource setup:
49 # file has a resource setup:
50 # map.resource('repo', 'repos')
50 # map.resource('repo', 'repos')
51
51
52 @LoginRequired()
52 @LoginRequired()
53 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
53 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
54 def __before__(self):
54 def __before__(self):
55 c.admin_user = session.get('admin_user')
55 c.admin_user = session.get('admin_user')
56 c.admin_username = session.get('admin_username')
56 c.admin_username = session.get('admin_username')
57 super(ReposController, self).__before__()
57 super(ReposController, self).__before__()
58
58
59 @HasPermissionAllDecorator('hg.admin')
59 @HasPermissionAllDecorator('hg.admin')
60 def index(self, format='html'):
60 def index(self, format='html'):
61 """GET /repos: All items in the collection"""
61 """GET /repos: All items in the collection"""
62 # url('repos')
62 # url('repos')
63 cached_repo_list = ScmModel().get_repos()
63 cached_repo_list = ScmModel().get_repos()
64 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
64 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
65 return render('admin/repos/repos.html')
65 return render('admin/repos/repos.html')
66
66
67 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
67 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
68 def create(self):
68 def create(self):
69 """POST /repos: Create a new item"""
69 """POST /repos: Create a new item"""
70 # url('repos')
70 # url('repos')
71 repo_model = RepoModel()
71 repo_model = RepoModel()
72 _form = RepoForm()()
72 _form = RepoForm()()
73 form_result = {}
73 form_result = {}
74 try:
74 try:
75 form_result = _form.to_python(dict(request.POST))
75 form_result = _form.to_python(dict(request.POST))
76 repo_model.create(form_result, c.rhodecode_user)
76 repo_model.create(form_result, c.rhodecode_user)
77 h.flash(_('created repository %s') % form_result['repo_name'],
77 h.flash(_('created repository %s') % form_result['repo_name'],
78 category='success')
78 category='success')
79
79
80 if request.POST.get('user_created'):
80 if request.POST.get('user_created'):
81 action_logger(self.rhodecode_user, 'user_created_repo',
81 action_logger(self.rhodecode_user, 'user_created_repo',
82 form_result['repo_name'], '', self.sa)
82 form_result['repo_name'], '', self.sa)
83 else:
83 else:
84 action_logger(self.rhodecode_user, 'admin_created_repo',
84 action_logger(self.rhodecode_user, 'admin_created_repo',
85 form_result['repo_name'], '', self.sa)
85 form_result['repo_name'], '', self.sa)
86
86
87 except formencode.Invalid, errors:
87 except formencode.Invalid, errors:
88 c.new_repo = errors.value['repo_name']
88 c.new_repo = errors.value['repo_name']
89
89
90 if request.POST.get('user_created'):
90 if request.POST.get('user_created'):
91 r = render('admin/repos/repo_add_create_repository.html')
91 r = render('admin/repos/repo_add_create_repository.html')
92 else:
92 else:
93 r = render('admin/repos/repo_add.html')
93 r = render('admin/repos/repo_add.html')
94
94
95 return htmlfill.render(
95 return htmlfill.render(
96 r,
96 r,
97 defaults=errors.value,
97 defaults=errors.value,
98 errors=errors.error_dict or {},
98 errors=errors.error_dict or {},
99 prefix_error=False,
99 prefix_error=False,
100 encoding="UTF-8")
100 encoding="UTF-8")
101
101
102 except Exception:
102 except Exception:
103 log.error(traceback.format_exc())
103 log.error(traceback.format_exc())
104 msg = _('error occured during creation of repository %s') \
104 msg = _('error occured during creation of repository %s') \
105 % form_result.get('repo_name')
105 % form_result.get('repo_name')
106 h.flash(msg, category='error')
106 h.flash(msg, category='error')
107 if request.POST.get('user_created'):
107 if request.POST.get('user_created'):
108 return redirect(url('home'))
108 return redirect(url('home'))
109 return redirect(url('repos'))
109 return redirect(url('repos'))
110
110
111 @HasPermissionAllDecorator('hg.admin')
111 @HasPermissionAllDecorator('hg.admin')
112 def new(self, format='html'):
112 def new(self, format='html'):
113 """GET /repos/new: Form to create a new item"""
113 """GET /repos/new: Form to create a new item"""
114 new_repo = request.GET.get('repo', '')
114 new_repo = request.GET.get('repo', '')
115 c.new_repo = h.repo_name_slug(new_repo)
115 c.new_repo = h.repo_name_slug(new_repo)
116
116
117 return render('admin/repos/repo_add.html')
117 return render('admin/repos/repo_add.html')
118
118
119 @HasPermissionAllDecorator('hg.admin')
119 @HasPermissionAllDecorator('hg.admin')
120 def update(self, repo_name):
120 def update(self, repo_name):
121 """PUT /repos/repo_name: Update an existing item"""
121 """PUT /repos/repo_name: Update an existing item"""
122 # Forms posted to this method should contain a hidden field:
122 # Forms posted to this method should contain a hidden field:
123 # <input type="hidden" name="_method" value="PUT" />
123 # <input type="hidden" name="_method" value="PUT" />
124 # Or using helpers:
124 # Or using helpers:
125 # h.form(url('repo', repo_name=ID),
125 # h.form(url('repo', repo_name=ID),
126 # method='put')
126 # method='put')
127 # url('repo', repo_name=ID)
127 # url('repo', repo_name=ID)
128 repo_model = RepoModel()
128 repo_model = RepoModel()
129 changed_name = repo_name
129 changed_name = repo_name
130 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
130 _form = RepoForm(edit=True, old_data={'repo_name':repo_name})()
131
131
132 try:
132 try:
133 form_result = _form.to_python(dict(request.POST))
133 form_result = _form.to_python(dict(request.POST))
134 repo_model.update(repo_name, form_result)
134 repo_model.update(repo_name, form_result)
135 invalidate_cache('get_repo_cached_%s' % repo_name)
135 invalidate_cache('get_repo_cached_%s' % repo_name)
136 h.flash(_('Repository %s updated successfully' % repo_name),
136 h.flash(_('Repository %s updated successfully' % repo_name),
137 category='success')
137 category='success')
138 changed_name = form_result['repo_name']
138 changed_name = form_result['repo_name']
139 action_logger(self.rhodecode_user, 'admin_updated_repo',
139 action_logger(self.rhodecode_user, 'admin_updated_repo',
140 changed_name, '', self.sa)
140 changed_name, '', self.sa)
141
141
142 except formencode.Invalid, errors:
142 except formencode.Invalid, errors:
143 c.repo_info = repo_model.get_by_repo_name(repo_name)
143 c.repo_info = repo_model.get_by_repo_name(repo_name)
144 if c.repo_info.stats:
145 last_rev = c.repo_info.stats.stat_on_revision
146 else:
147 last_rev = 0
148 c.stats_revision = last_rev
149 r = ScmModel().get(repo_name)
150 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
151
152 if last_rev == 0:
153 c.stats_percentage = 0
154 else:
155 c.stats_percentage = '%.2f' % ((float((last_rev)) /
156 c.repo_last_rev) * 100)
157
144 c.users_array = repo_model.get_users_js()
158 c.users_array = repo_model.get_users_js()
145 errors.value.update({'user':c.repo_info.user.username})
159 errors.value.update({'user':c.repo_info.user.username})
146 return htmlfill.render(
160 return htmlfill.render(
147 render('admin/repos/repo_edit.html'),
161 render('admin/repos/repo_edit.html'),
148 defaults=errors.value,
162 defaults=errors.value,
149 errors=errors.error_dict or {},
163 errors=errors.error_dict or {},
150 prefix_error=False,
164 prefix_error=False,
151 encoding="UTF-8")
165 encoding="UTF-8")
152
166
153 except Exception:
167 except Exception:
154 log.error(traceback.format_exc())
168 log.error(traceback.format_exc())
155 h.flash(_('error occurred during update of repository %s') \
169 h.flash(_('error occurred during update of repository %s') \
156 % repo_name, category='error')
170 % repo_name, category='error')
157
171
158 return redirect(url('edit_repo', repo_name=changed_name))
172 return redirect(url('edit_repo', repo_name=changed_name))
159
173
160 @HasPermissionAllDecorator('hg.admin')
174 @HasPermissionAllDecorator('hg.admin')
161 def delete(self, repo_name):
175 def delete(self, repo_name):
162 """DELETE /repos/repo_name: Delete an existing item"""
176 """DELETE /repos/repo_name: Delete an existing item"""
163 # Forms posted to this method should contain a hidden field:
177 # Forms posted to this method should contain a hidden field:
164 # <input type="hidden" name="_method" value="DELETE" />
178 # <input type="hidden" name="_method" value="DELETE" />
165 # Or using helpers:
179 # Or using helpers:
166 # h.form(url('repo', repo_name=ID),
180 # h.form(url('repo', repo_name=ID),
167 # method='delete')
181 # method='delete')
168 # url('repo', repo_name=ID)
182 # url('repo', repo_name=ID)
169
183
170 repo_model = RepoModel()
184 repo_model = RepoModel()
171 repo = repo_model.get_by_repo_name(repo_name)
185 repo = repo_model.get_by_repo_name(repo_name)
172 if not repo:
186 if not repo:
173 h.flash(_('%s repository is not mapped to db perhaps'
187 h.flash(_('%s repository is not mapped to db perhaps'
174 ' it was moved or renamed from the filesystem'
188 ' it was moved or renamed from the filesystem'
175 ' please run the application again'
189 ' please run the application again'
176 ' in order to rescan repositories') % repo_name,
190 ' in order to rescan repositories') % repo_name,
177 category='error')
191 category='error')
178
192
179 return redirect(url('repos'))
193 return redirect(url('repos'))
180 try:
194 try:
181 action_logger(self.rhodecode_user, 'admin_deleted_repo',
195 action_logger(self.rhodecode_user, 'admin_deleted_repo',
182 repo_name, '', self.sa)
196 repo_name, '', self.sa)
183 repo_model.delete(repo)
197 repo_model.delete(repo)
184 invalidate_cache('get_repo_cached_%s' % repo_name)
198 invalidate_cache('get_repo_cached_%s' % repo_name)
185 h.flash(_('deleted repository %s') % repo_name, category='success')
199 h.flash(_('deleted repository %s') % repo_name, category='success')
186
200
187 except Exception, e:
201 except Exception, e:
188 log.error(traceback.format_exc())
202 log.error(traceback.format_exc())
189 h.flash(_('An error occured during deletion of %s') % repo_name,
203 h.flash(_('An error occured during deletion of %s') % repo_name,
190 category='error')
204 category='error')
191
205
192 return redirect(url('repos'))
206 return redirect(url('repos'))
193
207
194 @HasPermissionAllDecorator('hg.admin')
208 @HasPermissionAllDecorator('hg.admin')
195 def delete_perm_user(self, repo_name):
209 def delete_perm_user(self, repo_name):
196 """
210 """
197 DELETE an existing repository permission user
211 DELETE an existing repository permission user
198 :param repo_name:
212 :param repo_name:
199 """
213 """
200
214
201 try:
215 try:
202 repo_model = RepoModel()
216 repo_model = RepoModel()
203 repo_model.delete_perm_user(request.POST, repo_name)
217 repo_model.delete_perm_user(request.POST, repo_name)
204 except Exception, e:
218 except Exception, e:
205 h.flash(_('An error occured during deletion of repository user'),
219 h.flash(_('An error occured during deletion of repository user'),
206 category='error')
220 category='error')
207 raise HTTPInternalServerError()
221 raise HTTPInternalServerError()
208
222
209 @HasPermissionAllDecorator('hg.admin')
223 @HasPermissionAllDecorator('hg.admin')
210 def repo_stats(self, repo_name):
224 def repo_stats(self, repo_name):
211 """
225 """
212 DELETE an existing repository statistics
226 DELETE an existing repository statistics
213 :param repo_name:
227 :param repo_name:
214 """
228 """
215
229
216 try:
230 try:
217 repo_model = RepoModel()
231 repo_model = RepoModel()
218 repo_model.delete_stats(repo_name)
232 repo_model.delete_stats(repo_name)
219 except Exception, e:
233 except Exception, e:
220 h.flash(_('An error occured during deletion of repository stats'),
234 h.flash(_('An error occured during deletion of repository stats'),
221 category='error')
235 category='error')
222 return redirect(url('edit_repo', repo_name=repo_name))
236 return redirect(url('edit_repo', repo_name=repo_name))
223
237
224 @HasPermissionAllDecorator('hg.admin')
238 @HasPermissionAllDecorator('hg.admin')
225 def repo_cache(self, repo_name):
239 def repo_cache(self, repo_name):
226 """
240 """
227 INVALIDATE exisitings repository cache
241 INVALIDATE exisitings repository cache
228 :param repo_name:
242 :param repo_name:
229 """
243 """
230
244
231 try:
245 try:
232 ScmModel().mark_for_invalidation(repo_name)
246 ScmModel().mark_for_invalidation(repo_name)
233 except Exception, e:
247 except Exception, e:
234 h.flash(_('An error occurred during cache invalidation'),
248 h.flash(_('An error occurred during cache invalidation'),
235 category='error')
249 category='error')
236 return redirect(url('edit_repo', repo_name=repo_name))
250 return redirect(url('edit_repo', repo_name=repo_name))
237
251
238 @HasPermissionAllDecorator('hg.admin')
252 @HasPermissionAllDecorator('hg.admin')
239 def show(self, repo_name, format='html'):
253 def show(self, repo_name, format='html'):
240 """GET /repos/repo_name: Show a specific item"""
254 """GET /repos/repo_name: Show a specific item"""
241 # url('repo', repo_name=ID)
255 # url('repo', repo_name=ID)
242
256
243 @HasPermissionAllDecorator('hg.admin')
257 @HasPermissionAllDecorator('hg.admin')
244 def edit(self, repo_name, format='html'):
258 def edit(self, repo_name, format='html'):
245 """GET /repos/repo_name/edit: Form to edit an existing item"""
259 """GET /repos/repo_name/edit: Form to edit an existing item"""
246 # url('edit_repo', repo_name=ID)
260 # url('edit_repo', repo_name=ID)
247 repo_model = RepoModel()
261 repo_model = RepoModel()
248 c.repo_info = repo = repo_model.get_by_repo_name(repo_name)
262 c.repo_info = repo_model.get_by_repo_name(repo_name)
249 if repo.stats:
263 if c.repo_info.stats:
250 last_rev = repo.stats.stat_on_revision
264 last_rev = c.repo_info.stats.stat_on_revision
251 else:
265 else:
252 last_rev = 0
266 last_rev = 0
253 c.stats_revision = last_rev
267 c.stats_revision = last_rev
254 r = ScmModel().get(repo_name)
268 r = ScmModel().get(repo_name)
255 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
269 c.repo_last_rev = r.revisions[-1] if r.revisions else 0
256
270
257 if last_rev == 0:
271 if last_rev == 0:
258 c.stats_percentage = 0
272 c.stats_percentage = 0
259 else:
273 else:
260 c.stats_percentage = '%.2f' % ((float((last_rev)) / c.repo_last_rev) * 100)
274 c.stats_percentage = '%.2f' % ((float((last_rev)) /
275 c.repo_last_rev) * 100)
261
276
262
277
263 if not repo:
278 if not c.repo_info:
264 h.flash(_('%s repository is not mapped to db perhaps'
279 h.flash(_('%s repository is not mapped to db perhaps'
265 ' it was created or renamed from the filesystem'
280 ' it was created or renamed from the filesystem'
266 ' please run the application again'
281 ' please run the application again'
267 ' in order to rescan repositories') % repo_name,
282 ' in order to rescan repositories') % repo_name,
268 category='error')
283 category='error')
269
284
270 return redirect(url('repos'))
285 return redirect(url('repos'))
271 defaults = c.repo_info.__dict__
286 defaults = c.repo_info.__dict__
272 if c.repo_info.user:
287 if c.repo_info.user:
273 defaults.update({'user':c.repo_info.user.username})
288 defaults.update({'user':c.repo_info.user.username})
274 else:
289 else:
275 replacement_user = self.sa.query(User)\
290 replacement_user = self.sa.query(User)\
276 .filter(User.admin == True).first().username
291 .filter(User.admin == True).first().username
277 defaults.update({'user':replacement_user})
292 defaults.update({'user':replacement_user})
278
293
279 c.users_array = repo_model.get_users_js()
294 c.users_array = repo_model.get_users_js()
280
295
281 for p in c.repo_info.repo_to_perm:
296 for p in c.repo_info.repo_to_perm:
282 defaults.update({'perm_%s' % p.user.username:
297 defaults.update({'perm_%s' % p.user.username:
283 p.permission.permission_name})
298 p.permission.permission_name})
284
299
285 return htmlfill.render(
300 return htmlfill.render(
286 render('admin/repos/repo_edit.html'),
301 render('admin/repos/repo_edit.html'),
287 defaults=defaults,
302 defaults=defaults,
288 encoding="UTF-8",
303 encoding="UTF-8",
289 force_defaults=False
304 force_defaults=False
290 )
305 )
General Comments 0
You need to be logged in to leave comments. Login now