##// END OF EJS Templates
bugfix for empty groups
marcink -
r1160:6e70fcca beta
parent child Browse files
Show More
@@ -1,422 +1,422 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.admin.repos
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Admin controller for RhodeCode
7 7
8 8 :created_on: Apr 7, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software; you can redistribute it and/or
14 14 # modify it under the terms of the GNU General Public License
15 15 # as published by the Free Software Foundation; version 2
16 16 # of the License or (at your opinion) any later version of the license.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program; if not, write to the Free Software
25 25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 26 # MA 02110-1301, USA.
27 27
28 28 import logging
29 29 import traceback
30 30 import formencode
31 31 from operator import itemgetter
32 32 from formencode import htmlfill
33 33
34 34 from paste.httpexceptions import HTTPInternalServerError
35 35 from pylons import request, response, session, tmpl_context as c, url
36 36 from pylons.controllers.util import abort, redirect
37 37 from pylons.i18n.translation import _
38 38
39 39 from rhodecode.lib import helpers as h
40 40 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \
41 41 HasPermissionAnyDecorator
42 42 from rhodecode.lib.base import BaseController, render
43 43 from rhodecode.lib.utils import invalidate_cache, action_logger, repo_name_slug
44 44 from rhodecode.lib.helpers import get_token
45 45 from rhodecode.model.db import User, Repository, UserFollowing, Group
46 46 from rhodecode.model.forms import RepoForm
47 47 from rhodecode.model.scm import ScmModel
48 48 from rhodecode.model.repo import RepoModel
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52 class ReposController(BaseController):
53 53 """
54 54 REST Controller styled on the Atom Publishing Protocol"""
55 55 # To properly map this controller, ensure your config/routing.py
56 56 # file has a resource setup:
57 57 # map.resource('repo', 'repos')
58 58
59 59 @LoginRequired()
60 60 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
61 61 def __before__(self):
62 62 c.admin_user = session.get('admin_user')
63 63 c.admin_username = session.get('admin_username')
64 64 super(ReposController, self).__before__()
65 65
66 66 def __load_defaults(self):
67 67 repo_model = RepoModel()
68 68
69 69 c.repo_groups = [('', '')]
70 70 parents_link = lambda k:h.literal('&raquo;'.join(
71 71 map(lambda k:k.group_name,
72 72 k.parents + [k])
73 73 )
74 74 )
75 75
76 76 c.repo_groups.extend([(x.group_id, parents_link(x)) for \
77 77 x in self.sa.query(Group).all()])
78 78 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
79 79 c.users_array = repo_model.get_users_js()
80 80 c.users_groups_array = repo_model.get_users_groups_js()
81 81
82 82 def __load_data(self, repo_name=None):
83 83 """
84 84 Load defaults settings for edit, and update
85 85
86 86 :param repo_name:
87 87 """
88 88 self.__load_defaults()
89 89
90 90 repo, dbrepo = ScmModel().get(repo_name, retval='repo')
91 91
92 92 repo_model = RepoModel()
93 93 c.repo_info = repo_model.get_by_repo_name(repo_name)
94 94
95 95
96 96 if c.repo_info is None:
97 97 h.flash(_('%s repository is not mapped to db perhaps'
98 98 ' it was created or renamed from the filesystem'
99 99 ' please run the application again'
100 100 ' in order to rescan repositories') % repo_name,
101 101 category='error')
102 102
103 103 return redirect(url('repos'))
104 104
105 105
106 106 c.default_user_id = User.by_username('default').user_id
107 107 c.in_public_journal = self.sa.query(UserFollowing)\
108 108 .filter(UserFollowing.user_id == c.default_user_id)\
109 109 .filter(UserFollowing.follows_repository == c.repo_info).scalar()
110 110
111 111 if c.repo_info.stats:
112 112 last_rev = c.repo_info.stats.stat_on_revision
113 113 else:
114 114 last_rev = 0
115 115 c.stats_revision = last_rev
116 116
117 117 c.repo_last_rev = repo.count() - 1 if repo.revisions else 0
118 118
119 119 if last_rev == 0 or c.repo_last_rev == 0:
120 120 c.stats_percentage = 0
121 121 else:
122 122 c.stats_percentage = '%.2f' % ((float((last_rev)) /
123 123 c.repo_last_rev) * 100)
124 124
125 125
126 126
127 127 defaults = c.repo_info.get_dict()
128 128 group, repo_name = c.repo_info.groups_and_repo
129 129 defaults['repo_name'] = repo_name
130 defaults['repo_group'] = getattr(group[-1], 'group_id', None)
130 defaults['repo_group'] = getattr(group[-1] if group else None, 'group_id', None)
131 131
132 132 #fill owner
133 133 if c.repo_info.user:
134 134 defaults.update({'user':c.repo_info.user.username})
135 135 else:
136 136 replacement_user = self.sa.query(User)\
137 137 .filter(User.admin == True).first().username
138 138 defaults.update({'user':replacement_user})
139 139
140 140
141 141 #fill repository users
142 142 for p in c.repo_info.repo_to_perm:
143 143 defaults.update({'u_perm_%s' % p.user.username:
144 144 p.permission.permission_name})
145 145
146 146 #fill repository groups
147 147 for p in c.repo_info.users_group_to_perm:
148 148 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
149 149 p.permission.permission_name})
150 150
151 151
152 152 return defaults
153 153
154 154
155 155 @HasPermissionAllDecorator('hg.admin')
156 156 def index(self, format='html'):
157 157 """GET /repos: All items in the collection"""
158 158 # url('repos')
159 159 cached_repo_list = ScmModel().get_repos()
160 160 c.repos_list = sorted(cached_repo_list, key=itemgetter('name_sort'))
161 161 return render('admin/repos/repos.html')
162 162
163 163 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
164 164 def create(self):
165 165 """
166 166 POST /repos: Create a new item"""
167 167 # url('repos')
168 168 repo_model = RepoModel()
169 169 self.__load_defaults()
170 170 form_result = {}
171 171 try:
172 172 form_result = RepoForm(repo_groups=c.repo_groups_choices)()\
173 173 .to_python(dict(request.POST))
174 174 repo_model.create(form_result, self.rhodecode_user)
175 175 if form_result['clone_uri']:
176 176 h.flash(_('created repository %s from %s') \
177 177 % (form_result['repo_name'], form_result['clone_uri']),
178 178 category='success')
179 179 else:
180 180 h.flash(_('created repository %s') % form_result['repo_name'],
181 181 category='success')
182 182
183 183 if request.POST.get('user_created'):
184 184 action_logger(self.rhodecode_user, 'user_created_repo',
185 185 form_result['repo_name'], '', self.sa)
186 186 else:
187 187 action_logger(self.rhodecode_user, 'admin_created_repo',
188 188 form_result['repo_name'], '', self.sa)
189 189
190 190 except formencode.Invalid, errors:
191 191
192 192 c.new_repo = errors.value['repo_name']
193 193
194 194 if request.POST.get('user_created'):
195 195 r = render('admin/repos/repo_add_create_repository.html')
196 196 else:
197 197 r = render('admin/repos/repo_add.html')
198 198
199 199 return htmlfill.render(
200 200 r,
201 201 defaults=errors.value,
202 202 errors=errors.error_dict or {},
203 203 prefix_error=False,
204 204 encoding="UTF-8")
205 205
206 206 except Exception:
207 207 log.error(traceback.format_exc())
208 208 msg = _('error occurred during creation of repository %s') \
209 209 % form_result.get('repo_name')
210 210 h.flash(msg, category='error')
211 211 if request.POST.get('user_created'):
212 212 return redirect(url('home'))
213 213 return redirect(url('repos'))
214 214
215 215 @HasPermissionAllDecorator('hg.admin')
216 216 def new(self, format='html'):
217 217 """GET /repos/new: Form to create a new item"""
218 218 new_repo = request.GET.get('repo', '')
219 219 c.new_repo = repo_name_slug(new_repo)
220 220 self.__load_defaults()
221 221 return render('admin/repos/repo_add.html')
222 222
223 223 @HasPermissionAllDecorator('hg.admin')
224 224 def update(self, repo_name):
225 225 """
226 226 PUT /repos/repo_name: Update an existing item"""
227 227 # Forms posted to this method should contain a hidden field:
228 228 # <input type="hidden" name="_method" value="PUT" />
229 229 # Or using helpers:
230 230 # h.form(url('repo', repo_name=ID),
231 231 # method='put')
232 232 # url('repo', repo_name=ID)
233 233 self.__load_defaults()
234 234 repo_model = RepoModel()
235 235 changed_name = repo_name
236 236 _form = RepoForm(edit=True, old_data={'repo_name':repo_name},
237 237 repo_groups=c.repo_groups_choices)()
238 238 try:
239 239 form_result = _form.to_python(dict(request.POST))
240 240 repo_model.update(repo_name, form_result)
241 241 invalidate_cache('get_repo_cached_%s' % repo_name)
242 242 h.flash(_('Repository %s updated successfully' % repo_name),
243 243 category='success')
244 244 changed_name = form_result['repo_name']
245 245 action_logger(self.rhodecode_user, 'admin_updated_repo',
246 246 changed_name, '', self.sa)
247 247
248 248 except formencode.Invalid, errors:
249 249 defaults = self.__load_data(repo_name)
250 250 defaults.update(errors.value)
251 251 return htmlfill.render(
252 252 render('admin/repos/repo_edit.html'),
253 253 defaults=defaults,
254 254 errors=errors.error_dict or {},
255 255 prefix_error=False,
256 256 encoding="UTF-8")
257 257
258 258 except Exception:
259 259 log.error(traceback.format_exc())
260 260 h.flash(_('error occurred during update of repository %s') \
261 261 % repo_name, category='error')
262 262 return redirect(url('edit_repo', repo_name=changed_name))
263 263
264 264 @HasPermissionAllDecorator('hg.admin')
265 265 def delete(self, repo_name):
266 266 """
267 267 DELETE /repos/repo_name: Delete an existing item"""
268 268 # Forms posted to this method should contain a hidden field:
269 269 # <input type="hidden" name="_method" value="DELETE" />
270 270 # Or using helpers:
271 271 # h.form(url('repo', repo_name=ID),
272 272 # method='delete')
273 273 # url('repo', repo_name=ID)
274 274
275 275 repo_model = RepoModel()
276 276 repo = repo_model.get_by_repo_name(repo_name)
277 277 if not repo:
278 278 h.flash(_('%s repository is not mapped to db perhaps'
279 279 ' it was moved or renamed from the filesystem'
280 280 ' please run the application again'
281 281 ' in order to rescan repositories') % repo_name,
282 282 category='error')
283 283
284 284 return redirect(url('repos'))
285 285 try:
286 286 action_logger(self.rhodecode_user, 'admin_deleted_repo',
287 287 repo_name, '', self.sa)
288 288 repo_model.delete(repo)
289 289 invalidate_cache('get_repo_cached_%s' % repo_name)
290 290 h.flash(_('deleted repository %s') % repo_name, category='success')
291 291
292 292 except Exception, e:
293 293 log.error(traceback.format_exc())
294 294 h.flash(_('An error occurred during deletion of %s') % repo_name,
295 295 category='error')
296 296
297 297 return redirect(url('repos'))
298 298
299 299 @HasPermissionAllDecorator('hg.admin')
300 300 def delete_perm_user(self, repo_name):
301 301 """
302 302 DELETE an existing repository permission user
303 303
304 304 :param repo_name:
305 305 """
306 306
307 307 try:
308 308 repo_model = RepoModel()
309 309 repo_model.delete_perm_user(request.POST, repo_name)
310 310 except Exception, e:
311 311 h.flash(_('An error occurred during deletion of repository user'),
312 312 category='error')
313 313 raise HTTPInternalServerError()
314 314
315 315 @HasPermissionAllDecorator('hg.admin')
316 316 def delete_perm_users_group(self, repo_name):
317 317 """
318 318 DELETE an existing repository permission users group
319 319
320 320 :param repo_name:
321 321 """
322 322 try:
323 323 repo_model = RepoModel()
324 324 repo_model.delete_perm_users_group(request.POST, repo_name)
325 325 except Exception, e:
326 326 h.flash(_('An error occurred during deletion of repository'
327 327 ' users groups'),
328 328 category='error')
329 329 raise HTTPInternalServerError()
330 330
331 331 @HasPermissionAllDecorator('hg.admin')
332 332 def repo_stats(self, repo_name):
333 333 """
334 334 DELETE an existing repository statistics
335 335
336 336 :param repo_name:
337 337 """
338 338
339 339 try:
340 340 repo_model = RepoModel()
341 341 repo_model.delete_stats(repo_name)
342 342 except Exception, e:
343 343 h.flash(_('An error occurred during deletion of repository stats'),
344 344 category='error')
345 345 return redirect(url('edit_repo', repo_name=repo_name))
346 346
347 347 @HasPermissionAllDecorator('hg.admin')
348 348 def repo_cache(self, repo_name):
349 349 """
350 350 INVALIDATE existing repository cache
351 351
352 352 :param repo_name:
353 353 """
354 354
355 355 try:
356 356 ScmModel().mark_for_invalidation(repo_name)
357 357 except Exception, e:
358 358 h.flash(_('An error occurred during cache invalidation'),
359 359 category='error')
360 360 return redirect(url('edit_repo', repo_name=repo_name))
361 361
362 362 @HasPermissionAllDecorator('hg.admin')
363 363 def repo_public_journal(self, repo_name):
364 364 """
365 365 Set's this repository to be visible in public journal,
366 366 in other words assing default user to follow this repo
367 367
368 368 :param repo_name:
369 369 """
370 370
371 371 cur_token = request.POST.get('auth_token')
372 372 token = get_token()
373 373 if cur_token == token:
374 374 try:
375 375 repo_id = Repository.by_repo_name(repo_name).repo_id
376 376 user_id = User.by_username('default').user_id
377 377 self.scm_model.toggle_following_repo(repo_id, user_id)
378 378 h.flash(_('Updated repository visibility in public journal'),
379 379 category='success')
380 380 except:
381 381 h.flash(_('An error occurred during setting this'
382 382 ' repository in public journal'),
383 383 category='error')
384 384
385 385 else:
386 386 h.flash(_('Token mismatch'), category='error')
387 387 return redirect(url('edit_repo', repo_name=repo_name))
388 388
389 389 @HasPermissionAllDecorator('hg.admin')
390 390 def repo_pull(self, repo_name):
391 391 """
392 392 Runs task to update given repository with remote changes,
393 393 ie. make pull on remote location
394 394
395 395 :param repo_name:
396 396 """
397 397 try:
398 398 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
399 399 h.flash(_('Pulled from remote location'), category='success')
400 400 except Exception, e:
401 401 h.flash(_('An error occurred during pull from remote location'),
402 402 category='error')
403 403
404 404 return redirect(url('edit_repo', repo_name=repo_name))
405 405
406 406 @HasPermissionAllDecorator('hg.admin')
407 407 def show(self, repo_name, format='html'):
408 408 """GET /repos/repo_name: Show a specific item"""
409 409 # url('repo', repo_name=ID)
410 410
411 411 @HasPermissionAllDecorator('hg.admin')
412 412 def edit(self, repo_name, format='html'):
413 413 """GET /repos/repo_name/edit: Form to edit an existing item"""
414 414 # url('edit_repo', repo_name=ID)
415 415 defaults = self.__load_data(repo_name)
416 416
417 417 return htmlfill.render(
418 418 render('admin/repos/repo_edit.html'),
419 419 defaults=defaults,
420 420 encoding="UTF-8",
421 421 force_defaults=False
422 422 )
General Comments 0
You need to be logged in to leave comments. Login now