##// END OF EJS Templates
bumped mercurial version
bumped mercurial version

File last commit:

r2973:9937afa7 beta
r3130:e054a668 beta
Show More
repos_groups.py
366 lines | 14.1 KiB | text/x-python | PythonLexer
2012 copyrights
r1824 # -*- coding: utf-8 -*-
"""
rhodecode.controllers.admin.repos_groups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#227 Initial version of repository groups permissions system...
r1982 Repositories groups controller for RhodeCode
2012 copyrights
r1824
:created_on: Mar 23, 2010
:author: marcink
:copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
:license: GPLv3, see COPYING for more details.
"""
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
changes for #56
r1171 import logging
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 import traceback
import formencode
from formencode import htmlfill
changes for #56
r1171
#227 Initial version of repository groups permissions system...
r1982 from pylons import request, tmpl_context as c, url
from pylons.controllers.util import redirect
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 from pylons.i18n.translation import _
changes for #56
r1171
Added friendly message about removing a group that still contains subgroups....
r1543 from sqlalchemy.exc import IntegrityError
lightweight dashboard fix for repos group
r2945 import rhodecode
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 from rhodecode.lib import helpers as h
lightweight dashboard fix for repos group
r2945 from rhodecode.lib.ext_json import json
#227 Initial version of repository groups permissions system...
r1982 from rhodecode.lib.auth import LoginRequired, HasPermissionAnyDecorator,\
HasReposGroupPermissionAnyDecorator
changes for #56
r1171 from rhodecode.lib.base import BaseController, render
lightweight dashboard fix for repos group
r2945 from rhodecode.model.db import RepoGroup, Repository
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 from rhodecode.model.repos_group import ReposGroupModel
from rhodecode.model.forms import ReposGroupForm
another major refactoring with session management
r1734 from rhodecode.model.meta import Session
#227 Initial version of repository groups permissions system...
r1982 from rhodecode.model.repo import RepoModel
Fixed bug in repos group discovery, when inner folder of bare git repos were detected as a group
r2497 from webob.exc import HTTPInternalServerError, HTTPNotFound
Permissions on group can be set in recursive mode setting defined permission to all children...
r2820 from rhodecode.lib.utils2 import str2bool
lightweight dashboard fix for repos group
r2945 from sqlalchemy.sql.expression import func
changes for #56
r1171
log = logging.getLogger(__name__)
PEP8ify - controllers
r1245
changes for #56
r1171 class ReposGroupsController(BaseController):
"""REST Controller styled on the Atom Publishing Protocol"""
# To properly map this controller, ensure your config/routing.py
# file has a resource setup:
# map.resource('repos_group', 'repos_groups')
#47 implemented basic edition of groups
r1347 @LoginRequired()
def __before__(self):
super(ReposGroupsController, self).__before__()
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 def __load_defaults(self):
refactoring of models names for repoGroup permissions
r1633 c.repo_groups = RepoGroup.groups_choices()
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
#227 Initial version of repository groups permissions system...
r1982 repo_model = RepoModel()
c.users_array = repo_model.get_users_js()
c.users_groups_array = repo_model.get_users_groups_js()
#47 implemented basic edition of groups
r1347 def __load_data(self, group_id):
"""
Load defaults settings for edit, and update
:param group_id:
"""
self.__load_defaults()
use get_or_404 where possible
r2496 repo_group = RepoGroup.get_or_404(group_id)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 data = repo_group.get_dict()
implements #226 repo groups available by path...
r1538 data['group_name'] = repo_group.name
#227 Initial version of repository groups permissions system...
r1982 # fill repository users
for p in repo_group.repo_group_to_perm:
data.update({'u_perm_%s' % p.user.username:
p.permission.permission_name})
# fill repository groups
for p in repo_group.users_group_to_perm:
data.update({'g_perm_%s' % p.users_group.users_group_name:
p.permission.permission_name})
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 return data
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345
@HasPermissionAnyDecorator('hg.admin')
changes for #56
r1171 def index(self, format='html'):
"""GET /repos_groups: All items in the collection"""
# url('repos_groups')
added validation to repo groups to check for conflicting repository name fixes #337
r1898 sk = lambda g: g.parents[0].group_name if g.parents else g.group_name
refactoring of models names for repoGroup permissions
r1633 c.groups = sorted(RepoGroup.query().all(), key=sk)
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 return render('admin/repos_groups/repos_groups_show.html')
@HasPermissionAnyDecorator('hg.admin')
changes for #56
r1171 def create(self):
"""POST /repos_groups: Create a new item"""
# url('repos_groups')
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 self.__load_defaults()
added validation to repo groups to check for conflicting repository name fixes #337
r1898 repos_group_form = ReposGroupForm(available_groups =
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 c.repo_groups_choices)()
try:
form_result = repos_group_form.to_python(dict(request.POST))
#227 Initial version of repository groups permissions system...
r1982 ReposGroupModel().create(
group_name=form_result['group_name'],
group_description=form_result['group_description'],
parent=form_result['group_parent_id']
)
sqlalchemy sessions cleanup in admin...
r2662 Session().commit()
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 h.flash(_('created repos group %s') \
#47 implemented basic edition of groups
r1347 % form_result['group_name'], category='success')
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 #TODO: in futureaction_logger(, '', '', '', self.sa)
except formencode.Invalid, errors:
changes for #56
r1171
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 return htmlfill.render(
render('admin/repos_groups/repos_groups_add.html'),
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
encoding="UTF-8")
except Exception:
log.error(traceback.format_exc())
h.flash(_('error occurred during creation of repos group %s') \
#47 implemented basic edition of groups
r1347 % request.POST.get('group_name'), category='error')
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345
return redirect(url('repos_groups'))
@HasPermissionAnyDecorator('hg.admin')
changes for #56
r1171 def new(self, format='html'):
"""GET /repos_groups/new: Form to create a new item"""
# url('new_repos_group')
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 self.__load_defaults()
return render('admin/repos_groups/repos_groups_add.html')
changes for #56
r1171
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 @HasPermissionAnyDecorator('hg.admin')
changes for #56
r1171 def update(self, id):
"""PUT /repos_groups/id: Update an existing item"""
# Forms posted to this method should contain a hidden field:
# <input type="hidden" name="_method" value="PUT" />
# Or using helpers:
# h.form(url('repos_group', id=ID),
# method='put')
# url('repos_group', id=ID)
#47 implemented basic edition of groups
r1347 self.__load_defaults()
refactoring of models names for repoGroup permissions
r1633 c.repos_group = RepoGroup.get(id)
#47 implemented basic edition of groups
r1347
#227 Initial version of repository groups permissions system...
r1982 repos_group_form = ReposGroupForm(
edit=True,
old_data=c.repos_group.get_dict(),
available_groups=c.repo_groups_choices
)()
#47 implemented basic edition of groups
r1347 try:
form_result = repos_group_form.to_python(dict(request.POST))
another major refactoring with session management
r1734 ReposGroupModel().update(id, form_result)
sqlalchemy sessions cleanup in admin...
r2662 Session().commit()
#47 implemented basic edition of groups
r1347 h.flash(_('updated repos group %s') \
% form_result['group_name'], category='success')
Permissions on group can be set in recursive mode setting defined permission to all children...
r2820 #TODO: in future action_logger(, '', '', '', self.sa)
#47 implemented basic edition of groups
r1347 except formencode.Invalid, errors:
return htmlfill.render(
render('admin/repos_groups/repos_groups_edit.html'),
defaults=errors.value,
errors=errors.error_dict or {},
prefix_error=False,
encoding="UTF-8")
except Exception:
log.error(traceback.format_exc())
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 h.flash(_('error occurred during update of repos group %s') \
#47 implemented basic edition of groups
r1347 % request.POST.get('group_name'), category='error')
Recursive set locking on all children of a group.
r2749 return redirect(url('edit_repos_group', id=id))
#47 implemented basic edition of groups
r1347
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 @HasPermissionAnyDecorator('hg.admin')
changes for #56
r1171 def delete(self, id):
"""DELETE /repos_groups/id: Delete an existing item"""
# Forms posted to this method should contain a hidden field:
# <input type="hidden" name="_method" value="DELETE" />
# Or using helpers:
# h.form(url('repos_group', id=ID),
# method='delete')
# url('repos_group', id=ID)
refactoring of models names for repoGroup permissions
r1633 gr = RepoGroup.get(id)
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 repos = gr.repositories.all()
if repos:
h.flash(_('This group contains %s repositores and cannot be '
Takumi IINO
i18n improve
r2570 'deleted') % len(repos),
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 category='error')
return redirect(url('repos_groups'))
try:
another major refactoring with session management
r1734 ReposGroupModel().delete(id)
sqlalchemy sessions cleanup in admin...
r2662 Session().commit()
Recursive set locking on all children of a group.
r2749 h.flash(_('removed repos group %s') % gr.group_name,
category='success')
removed obsolete sort code
r1482 #TODO: in future action_logger(, '', '', '', self.sa)
Added friendly message about removing a group that still contains subgroups....
r1543 except IntegrityError, e:
Recursive set locking on all children of a group.
r2749 if str(e.message).find('groups_group_parent_id_fkey') != -1:
Added friendly message about removing a group that still contains subgroups....
r1543 log.error(traceback.format_exc())
h.flash(_('Cannot delete this group it still contains '
'subgroups'),
category='warning')
else:
log.error(traceback.format_exc())
h.flash(_('error occurred during deletion of repos '
Takumi IINO
i18n improve
r2570 'group %s') % gr.group_name, category='error')
Added friendly message about removing a group that still contains subgroups....
r1543
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346 except Exception:
log.error(traceback.format_exc())
Added friendly message about removing a group that still contains subgroups....
r1543 h.flash(_('error occurred during deletion of repos '
Takumi IINO
i18n improve
r2570 'group %s') % gr.group_name, category='error')
#47 implemented deleting of empty groups. Fixed problem with full paths on nested groups
r1346
return redirect(url('repos_groups'))
#227 Initial version of repository groups permissions system...
r1982 @HasReposGroupPermissionAnyDecorator('group.admin')
def delete_repos_group_user_perm(self, group_name):
"""
DELETE an existing repositories group permission user
:param group_name:
"""
try:
Permissions on group can be set in recursive mode setting defined permission to all children...
r2820 recursive = str2bool(request.POST.get('recursive', False))
ReposGroupModel().delete_permission(
repos_group=group_name, obj=request.POST['user_id'],
obj_type='user', recursive=recursive
#227 Initial version of repository groups permissions system...
r1982 )
sqlalchemy sessions cleanup in admin...
r2662 Session().commit()
#227 Initial version of repository groups permissions system...
r1982 except Exception:
log.error(traceback.format_exc())
h.flash(_('An error occurred during deletion of group user'),
category='error')
raise HTTPInternalServerError()
@HasReposGroupPermissionAnyDecorator('group.admin')
def delete_repos_group_users_group_perm(self, group_name):
"""
DELETE an existing repositories group permission users group
:param group_name:
"""
try:
Permissions on group can be set in recursive mode setting defined permission to all children...
r2820 recursive = str2bool(request.POST.get('recursive', False))
ReposGroupModel().delete_permission(
repos_group=group_name, obj=request.POST['users_group_id'],
obj_type='users_group', recursive=recursive
#227 Initial version of repository groups permissions system...
r1982 )
sqlalchemy sessions cleanup in admin...
r2662 Session().commit()
#227 Initial version of repository groups permissions system...
r1982 except Exception:
log.error(traceback.format_exc())
h.flash(_('An error occurred during deletion of group'
' users groups'),
category='error')
raise HTTPInternalServerError()
implements #226 repo groups available by path...
r1538 def show_by_name(self, group_name):
fixed issue #370
r2055 """
This is a proxy that does a lookup group_name -> id, and shows
the group by id view instead
"""
group_name = group_name.rstrip('/')
Fixed bug in repos group discovery, when inner folder of bare git repos were detected as a group
r2497 id_ = RepoGroup.get_by_group_name(group_name)
if id_:
return self.show(id_.group_id)
raise HTTPNotFound
implements #226 repo groups available by path...
r1538
#227 Initial version of repository groups permissions system...
r1982 @HasReposGroupPermissionAnyDecorator('group.read', 'group.write',
'group.admin')
changes for #56
r1171 def show(self, id, format='html'):
"""GET /repos_groups/id: Show a specific item"""
# url('repos_group', id=ID)
use get_or_404 where possible
r2496 c.group = RepoGroup.get_or_404(id)
c.group_repos = c.group.repositories.all()
Added repo group page showing what reposiories are inside a group
r1193
#overwrite our cached list with current filter
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 gr_filter = c.group_repos
c.repo_cnt = 0
#47 implemented basic gui for browsing repo groups
r1343
Wraps group listing with permissions check so they don't get displayed
r2831 groups = RepoGroup.query().order_by(RepoGroup.group_name)\
refactoring of models names for repoGroup permissions
r1633 .filter(RepoGroup.group_parent_id == id).all()
Wraps group listing with permissions check so they don't get displayed
r2831 c.groups = self.scm_model.get_repos_groups(groups)
lightweight dashboard fix for repos group
r2945
if c.visual.lightweight_dashboard is False:
c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter)
c.repos_list = c.cached_repo_list
## lightweight version of dashboard
else:
c.repos_list = Repository.query()\
.filter(Repository.group_id == id)\
.order_by(func.lower(Repository.repo_name))\
.all()
repos_data = []
total_records = len(c.repos_list)
_tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
quick_menu = lambda repo_name: (template.get_def("quick_menu")
.render(repo_name, _=_, h=h, c=c))
repo_lnk = lambda name, rtype, private, fork_of: (
template.get_def("repo_name")
.render(name, rtype, private, fork_of, short_name=False,
admin=False, _=_, h=h, c=c))
last_change = lambda last_change: (template.get_def("last_change")
.render(last_change, _=_, h=h, c=c))
rss_lnk = lambda repo_name: (template.get_def("rss")
.render(repo_name, _=_, h=h, c=c))
atom_lnk = lambda repo_name: (template.get_def("atom")
.render(repo_name, _=_, h=h, c=c))
for repo in c.repos_list:
repos_data.append({
"menu": quick_menu(repo.repo_name),
"raw_name": repo.repo_name.lower(),
"name": repo_lnk(repo.repo_name, repo.repo_type,
repo.private, repo.fork),
"last_change": last_change(repo.last_db_change),
"desc": repo.description,
"owner": h.person(repo.user.username),
"rss": rss_lnk(repo.repo_name),
"atom": atom_lnk(repo.repo_name),
})
c.data = json.dumps({
"totalRecords": total_records,
"startIndex": 0,
"sort": "name",
"dir": "asc",
"records": repos_data
whitespace cleanup
r2973 })
Added repo group page showing what reposiories are inside a group
r1193 return render('admin/repos_groups/repos_groups.html')
#47 implemented Adding of new repo_groups+forms+validators. Fixed sorting of repo groups by main names in multiple locations. Removed some unneeded calls to self.sa for exchange to .query() methods....
r1345 @HasPermissionAnyDecorator('hg.admin')
changes for #56
r1171 def edit(self, id, format='html'):
"""GET /repos_groups/id/edit: Form to edit an existing item"""
# url('edit_repos_group', id=ID)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349
Added quick links for editing permissions for users from permission overview
r2631 c.repos_group = ReposGroupModel()._get_repos_group(id)
defaults = self.__load_data(c.repos_group.group_id)
#47 implemented basic edition of groups
r1347
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349 # we need to exclude this group from the group list for editing
Added quick links for editing permissions for users from permission overview
r2631 c.repo_groups = filter(lambda x: x[0] != c.repos_group.group_id,
c.repo_groups)
#47 added editing of groups, and moving them between. Added check constraint for groups...
r1349
#47 implemented basic edition of groups
r1347 return htmlfill.render(
render('admin/repos_groups/repos_groups_edit.html'),
defaults=defaults,
encoding="UTF-8",
force_defaults=False
)