@@ -67,94 +67,115 @@ class ReposGroupsController(BaseControll
form_result = repos_group_form.to_python(dict(request.POST))
repos_group_model.create(form_result)
h.flash(_('created repos group %s') \
% form_result['repos_group_name'], category='success')
#TODO: in futureaction_logger(, '', '', '', self.sa)
except formencode.Invalid, errors:
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') \
% request.POST.get('repos_group_name'), category='error')
return redirect(url('repos_groups'))
@HasPermissionAnyDecorator('hg.admin')
def new(self, format='html'):
"""GET /repos_groups/new: Form to create a new item"""
# url('new_repos_group')
self.__load_defaults()
return render('admin/repos_groups/repos_groups_add.html')
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)
def delete(self, id):
"""DELETE /repos_groups/id: Delete an existing item"""
# <input type="hidden" name="_method" value="DELETE" />
# method='delete')
repos_group_model = ReposGroupModel()
gr = Group.get(id)
repos = gr.repositories.all()
if repos:
h.flash(_('This group contains %s repositores and cannot be '
'deleted' % len(repos)),
category='error')
try:
repos_group_model.delete(id)
h.flash(_('removed repos group %s' % gr.group_name), category='success')
h.flash(_('error occurred during deletion of repos group %s' % gr.group_name),
def show(self, id, format='html'):
"""GET /repos_groups/id: Show a specific item"""
c.group = Group.get(id)
if c.group:
c.group_repos = c.group.repositories.all()
else:
return redirect(url('repos_group'))
sortables = ['name', 'description', 'last_change', 'tip', 'owner']
current_sort = request.GET.get('sort', 'name')
current_sort_slug = current_sort.replace('-', '')
if current_sort_slug not in sortables:
c.sort_by = 'name'
current_sort_slug = c.sort_by
c.sort_by = current_sort
c.sort_slug = current_sort_slug
sort_key = current_sort_slug + '_sort'
#overwrite our cached list with current filter
gr_filter = [r.repo_name for r in c.group_repos]
c.cached_repo_list = self.scm_model.get_repos(all_repos=gr_filter)
if c.sort_by.startswith('-'):
c.repos_list = sorted(c.cached_repo_list, key=itemgetter(sort_key),
reverse=True)
reverse=False)
c.repo_cnt = len(c.repos_list)
c.groups = self.sa.query(Group).order_by(Group.group_name)\
.filter(Group.group_parent_id == id).all()
return render('admin/repos_groups/repos_groups.html')
def edit(self, id, format='html'):
"""GET /repos_groups/id/edit: Form to edit an existing item"""
# url('edit_repos_group', id=ID)
@@ -275,115 +275,120 @@ class Repository(Base):
@property
def just_name(self):
return self.repo_name.split(os.sep)[-1]
def groups_with_parents(self):
groups = []
if self.group is None:
return groups
cur_gr = self.group
groups.insert(0, cur_gr)
while 1:
gr = getattr(cur_gr, 'parent_group', None)
cur_gr = cur_gr.parent_group
if gr is None:
break
groups.insert(0, gr)
def groups_and_repo(self):
return self.groups_with_parents, self.just_name
class Group(Base):
__tablename__ = 'groups'
__table_args__ = (UniqueConstraint('group_name', 'group_parent_id'), {'useexisting':True},)
__mapper_args__ = {'order_by':'group_name'}
group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
group_name = Column("group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
group_description = Column("group_description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
parent_group = relationship('Group', remote_side=group_id)
def __init__(self, group_name='', parent_group=None):
self.group_name = group_name
self.parent_group = parent_group
def __repr__(self):
return "<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
self.group_name)
@classmethod
def url_sep(cls):
return '/'
def parents(self):
if self.parent_group is None:
cur_gr = self.parent_group
def full_path(self):
return '/'.join([g.group_name for g in self.parents] +
return Group.url_sep().join([g.group_name for g in self.parents] +
[self.group_name])
def repositories(self):
return Session.query(Repository).filter(Repository.group == self)
class Permission(Base):
__tablename__ = 'permissions'
__table_args__ = {'useexisting':True}
permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
permission_name = Column("permission_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
permission_longname = Column("permission_longname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
return "<%s('%s:%s')>" % (self.__class__.__name__,
self.permission_id, self.permission_name)
def get_by_key(cls, key):
return Session.query(cls).filter(cls.permission_name == key).scalar()
class RepoToPerm(Base):
__tablename__ = 'repo_to_perm'
__table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'useexisting':True})
repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
user = relationship('User')
permission = relationship('Permission')
repository = relationship('Repository')
class UserToPerm(Base):
__tablename__ = 'user_to_perm'
__table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'useexisting':True})
user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
def has_perm(cls, user_id, perm):
if not isinstance(perm, Permission):
raise Exception('perm needs to be an instance of Permission class')
@@ -192,99 +192,99 @@ class ValidAuth(formencode.validators.Fa
def validate_python(self, value, state):
password = value['password']
username = value['username']
user = UserModel().get_by_username(username)
if authenticate(username, password):
return value
if user and user.active is False:
log.warning('user %s is disabled', username)
raise formencode.Invalid(self.message('disabled_account',
state=State_obj),
value, state,
error_dict=self.e_dict_disable)
log.warning('user %s not authenticated', username)
raise formencode.Invalid(self.message('invalid_password',
state=State_obj), value, state,
error_dict=self.e_dict)
class ValidRepoUser(formencode.validators.FancyValidator):
def to_python(self, value, state):
self.user_db = User.query()\
.filter(User.active == True)\
.filter(User.username == value).one()
raise formencode.Invalid(_('This username is not valid'),
value, state)
def ValidRepoName(edit, old_data):
class _ValidRepoName(formencode.validators.FancyValidator):
repo_name = value.get('repo_name')
slug = repo_name_slug(repo_name)
if slug in ['_admin', '']:
e_dict = {'repo_name': _('This repository name is disallowed')}
raise formencode.Invalid('', value, state, error_dict=e_dict)
if value.get('repo_group'):
gr = Group.get(value.get('repo_group'))
group_path = gr.full_path
# value needs to be aware of group name
# it has to use '/'
repo_name_full = group_path + '/' + repo_name
# value needs to be aware of group name in order to check
# db key
repo_name_full = group_path + Group.url_sep() + repo_name
group_path = ''
repo_name_full = repo_name
value['repo_name_full'] = repo_name_full
if old_data.get('repo_name') != repo_name_full or not edit:
if group_path != '':
if RepoModel().get_by_repo_name(repo_name_full,):
e_dict = {'repo_name':_('This repository already '
'exists in group "%s"') %
gr.group_name}
raise formencode.Invalid('', value, state,
error_dict=e_dict)
if RepoModel().get_by_repo_name(repo_name_full):
e_dict = {'repo_name':_('This repository '
'already exists')}
return _ValidRepoName
def SlugifyName():
class _SlugifyName(formencode.validators.FancyValidator):
return repo_name_slug(value)
return _SlugifyName
def ValidCloneUri():
from mercurial.httprepo import httprepository, httpsrepository
from rhodecode.lib.utils import make_ui
class _ValidCloneUri(formencode.validators.FancyValidator):
if not value:
pass
elif value.startswith('https'):
httpsrepository(make_ui('db'), value).capabilities
except Exception, e:
@@ -13,121 +13,126 @@
# 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/>.
import os
import logging
import traceback
from pylons.i18n.translation import _
from vcs.utils.lazy import LazyProperty
from rhodecode.model import BaseModel
from rhodecode.model.caching_query import FromCache
from rhodecode.model.db import Group, RhodeCodeUi
log = logging.getLogger(__name__)
class ReposGroupModel(BaseModel):
@LazyProperty
def repos_path(self):
"""
Get's the repositories root path from database
q = RhodeCodeUi.get_by_key('/').one()
return q.ui_value
def __create_group(self, group_name, parent_id):
makes repositories group on filesystem
:param repo_name:
:param parent_id:
if parent_id:
parent_group_name = Group.get(parent_id).group_name
paths = Group.get(parent_id).full_path.split(Group.url_sep())
parent_path = os.sep.join(paths)
parent_group_name = ''
parent_path = ''
create_path = os.path.join(self.repos_path, parent_group_name,
group_name)
create_path = os.path.join(self.repos_path, parent_path, group_name)
log.debug('creating new group in %s', create_path)
if os.path.isdir(create_path):
raise Exception('That directory already exists !')
os.makedirs(create_path)
def __rename_group(self, group_name):
Renames a group on filesystem
:param group_name:
def __delete_group(self, group_name):
def __delete_group(self, group):
Deletes a group from a filesystem
:param group: instance of group from database
paths = group.full_path.split(Group.url_sep())
paths = os.sep.join(paths)
rm_path = os.path.join(self.repos_path, paths)
os.rmdir(rm_path)
def create(self, form_data):
new_repos_group = Group()
new_repos_group.group_name = form_data['repos_group_name']
new_repos_group.group_description = \
form_data['repos_group_description']
new_repos_group.group_parent_id = form_data['repos_group_parent']
self.sa.add(new_repos_group)
self.__create_group(form_data['repos_group_name'],
form_data['repos_group_parent'])
self.sa.commit()
except:
self.sa.rollback()
raise
def update(self, repos_group_id, form_data):
repos_group = Group.get(repos_group_id)
self.sa.add(repos_group)
def delete(self, users_group_id):
users_group = self.get(users_group_id, cache=False)
users_group = Group.get(users_group_id)
self.sa.delete(users_group)
self.__delete_group(users_group)
Status change: