Changeset - fa6ba6727475
[Not reviewed]
beta
0 29 0
Mads Kiilerich - 13 years ago 2013-02-27 17:18:43
madski@unity3d.com
further cleanup of UsersGroup

Renaming some names ... but trying not to change API or database scheme.
29 files changed with 356 insertions and 356 deletions:
0 comments (0 inline, 0 general)
rhodecode/controllers/admin/users_groups.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.controllers.admin.users_groups
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    User Groups crud controller for pylons
 

	
 
    :created_on: Jan 25, 2011
 
    :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/>.
 

	
 
import logging
 
import traceback
 
import formencode
 

	
 
from formencode import htmlfill
 
from pylons import request, session, tmpl_context as c, url, config
 
from pylons.controllers.util import abort, redirect
 
from pylons.i18n.translation import _
 

	
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.exceptions import UsersGroupsAssignedException
 
from rhodecode.lib.exceptions import UserGroupsAssignedException
 
from rhodecode.lib.utils2 import safe_unicode, str2bool
 
from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
 
from rhodecode.lib.base import BaseController, render
 

	
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 

	
 
from rhodecode.model.db import User, UsersGroup, UsersGroupToPerm,\
 
    UsersGroupRepoToPerm, UsersGroupRepoGroupToPerm
 
from rhodecode.model.forms import UsersGroupForm
 
from rhodecode.model.db import User, UserGroup, UserGroupToPerm,\
 
    UserGroupRepoToPerm, UserGroupRepoGroupToPerm
 
from rhodecode.model.forms import UserGroupForm
 
from rhodecode.model.meta import Session
 
from rhodecode.lib.utils import action_logger
 
from sqlalchemy.orm import joinedload
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UsersGroupsController(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('users_group', 'users_groups')
 

	
 
    @LoginRequired()
 
    @HasPermissionAllDecorator('hg.admin')
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        super(UsersGroupsController, self).__before__()
 
        c.available_permissions = config['available_permissions']
 

	
 
    def index(self, format='html'):
 
        """GET /users_groups: All items in the collection"""
 
        # url('users_groups')
 
        c.users_groups_list = UsersGroup().query().all()
 
        c.users_groups_list = UserGroup().query().all()
 
        return render('admin/users_groups/users_groups.html')
 

	
 
    def create(self):
 
        """POST /users_groups: Create a new item"""
 
        # url('users_groups')
 

	
 
        users_group_form = UsersGroupForm()()
 
        users_group_form = UserGroupForm()()
 
        try:
 
            form_result = users_group_form.to_python(dict(request.POST))
 
            UsersGroupModel().create(name=form_result['users_group_name'],
 
            UserGroupModel().create(name=form_result['users_group_name'],
 
                                     active=form_result['users_group_active'])
 
            gr = form_result['users_group_name']
 
            action_logger(self.rhodecode_user,
 
                          'admin_created_users_group:%s' % gr,
 
                          None, self.ip_addr, self.sa)
 
            h.flash(_('created user group %s') % gr, category='success')
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            return htmlfill.render(
 
                render('admin/users_groups/users_group_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 user group %s') \
 
                    % request.POST.get('users_group_name'), category='error')
 

	
 
        return redirect(url('users_groups'))
 

	
 
    def new(self, format='html'):
 
        """GET /users_groups/new: Form to create a new item"""
 
        # url('new_users_group')
 
        return render('admin/users_groups/users_group_add.html')
 

	
 
    def _load_data(self, id):
 
        c.users_group.permissions = {
 
            'repositories': {},
 
            'repositories_groups': {}
 
        }
 

	
 
        ugroup_repo_perms = UsersGroupRepoToPerm.query()\
 
            .options(joinedload(UsersGroupRepoToPerm.permission))\
 
            .options(joinedload(UsersGroupRepoToPerm.repository))\
 
            .filter(UsersGroupRepoToPerm.users_group_id == id)\
 
        ugroup_repo_perms = UserGroupRepoToPerm.query()\
 
            .options(joinedload(UserGroupRepoToPerm.permission))\
 
            .options(joinedload(UserGroupRepoToPerm.repository))\
 
            .filter(UserGroupRepoToPerm.users_group_id == id)\
 
            .all()
 

	
 
        for gr in ugroup_repo_perms:
 
            c.users_group.permissions['repositories'][gr.repository.repo_name]  \
 
                = gr.permission.permission_name
 

	
 
        ugroup_group_perms = UsersGroupRepoGroupToPerm.query()\
 
            .options(joinedload(UsersGroupRepoGroupToPerm.permission))\
 
            .options(joinedload(UsersGroupRepoGroupToPerm.group))\
 
            .filter(UsersGroupRepoGroupToPerm.users_group_id == id)\
 
        ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
 
            .options(joinedload(UserGroupRepoGroupToPerm.permission))\
 
            .options(joinedload(UserGroupRepoGroupToPerm.group))\
 
            .filter(UserGroupRepoGroupToPerm.users_group_id == id)\
 
            .all()
 

	
 
        for gr in ugroup_group_perms:
 
            c.users_group.permissions['repositories_groups'][gr.group.group_name] \
 
                = gr.permission.permission_name
 

	
 
        c.group_members_obj = [x.user for x in c.users_group.members]
 
        c.group_members = [(x.user_id, x.username) for x in
 
                           c.group_members_obj]
 
        c.available_members = [(x.user_id, x.username) for x in
 
                               User.query().all()]
 

	
 
    def update(self, id):
 
        """PUT /users_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('users_group', id=ID),
 
        #           method='put')
 
        # url('users_group', id=ID)
 

	
 
        c.users_group = UsersGroup.get_or_404(id)
 
        c.users_group = UserGroup.get_or_404(id)
 
        self._load_data(id)
 

	
 
        available_members = [safe_unicode(x[0]) for x in c.available_members]
 

	
 
        users_group_form = UsersGroupForm(edit=True,
 
        users_group_form = UserGroupForm(edit=True,
 
                                          old_data=c.users_group.get_dict(),
 
                                          available_members=available_members)()
 

	
 
        try:
 
            form_result = users_group_form.to_python(request.POST)
 
            UsersGroupModel().update(c.users_group, form_result)
 
            UserGroupModel().update(c.users_group, form_result)
 
            gr = form_result['users_group_name']
 
            action_logger(self.rhodecode_user,
 
                          'admin_updated_users_group:%s' % gr,
 
                          None, self.ip_addr, self.sa)
 
            h.flash(_('updated user group %s') % gr, category='success')
 
            Session().commit()
 
        except formencode.Invalid, errors:
 
            ug_model = UsersGroupModel()
 
            ug_model = UserGroupModel()
 
            defaults = errors.value
 
            e = errors.error_dict or {}
 
            defaults.update({
 
                'create_repo_perm': ug_model.has_perm(id,
 
                                                      'hg.create.repository'),
 
                'fork_repo_perm': ug_model.has_perm(id,
 
                                                    'hg.fork.repository'),
 
                '_method': 'put'
 
            })
 

	
 
            return htmlfill.render(
 
                render('admin/users_groups/users_group_edit.html'),
 
                defaults=defaults,
 
                errors=e,
 
                prefix_error=False,
 
                encoding="UTF-8")
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('error occurred during update of user group %s') \
 
                    % request.POST.get('users_group_name'), category='error')
 

	
 
        return redirect(url('edit_users_group', id=id))
 

	
 
    def delete(self, id):
 
        """DELETE /users_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('users_group', id=ID),
 
        #           method='delete')
 
        # url('users_group', id=ID)
 
        usr_gr = UsersGroup.get_or_404(id)
 
        usr_gr = UserGroup.get_or_404(id)
 
        try:
 
            UsersGroupModel().delete(usr_gr)
 
            UserGroupModel().delete(usr_gr)
 
            Session().commit()
 
            h.flash(_('successfully deleted user group'), category='success')
 
        except UsersGroupsAssignedException, e:
 
        except UserGroupsAssignedException, e:
 
            h.flash(e, category='error')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during deletion of user group'),
 
                    category='error')
 
        return redirect(url('users_groups'))
 

	
 
    def show(self, id, format='html'):
 
        """GET /users_groups/id: Show a specific item"""
 
        # url('users_group', id=ID)
 

	
 
    def edit(self, id, format='html'):
 
        """GET /users_groups/id/edit: Form to edit an existing item"""
 
        # url('edit_users_group', id=ID)
 

	
 
        c.users_group = UsersGroup.get_or_404(id)
 
        c.users_group = UserGroup.get_or_404(id)
 
        self._load_data(id)
 

	
 
        ug_model = UsersGroupModel()
 
        ug_model = UserGroupModel()
 
        defaults = c.users_group.get_dict()
 
        defaults.update({
 
            'create_repo_perm': ug_model.has_perm(c.users_group,
 
                                                  'hg.create.repository'),
 
            'fork_repo_perm': ug_model.has_perm(c.users_group,
 
                                                'hg.fork.repository'),
 
        })
 

	
 
        return htmlfill.render(
 
            render('admin/users_groups/users_group_edit.html'),
 
            defaults=defaults,
 
            encoding="UTF-8",
 
            force_defaults=False
 
        )
 

	
 
    def update_perm(self, id):
 
        """PUT /users_perm/id: Update an existing item"""
 
        # url('users_group_perm', id=ID, method='put')
 

	
 
        users_group = UsersGroup.get_or_404(id)
 
        users_group = UserGroup.get_or_404(id)
 
        grant_create_perm = str2bool(request.POST.get('create_repo_perm'))
 
        grant_fork_perm = str2bool(request.POST.get('fork_repo_perm'))
 
        inherit_perms = str2bool(request.POST.get('inherit_default_permissions'))
 

	
 
        usersgroup_model = UsersGroupModel()
 
        usergroup_model = UserGroupModel()
 

	
 
        try:
 
            users_group.inherit_default_permissions = inherit_perms
 
            Session().add(users_group)
 

	
 
            if grant_create_perm:
 
                usersgroup_model.revoke_perm(id, 'hg.create.none')
 
                usersgroup_model.grant_perm(id, 'hg.create.repository')
 
                usergroup_model.revoke_perm(id, 'hg.create.none')
 
                usergroup_model.grant_perm(id, 'hg.create.repository')
 
                h.flash(_("Granted 'repository create' permission to user group"),
 
                        category='success')
 
            else:
 
                usersgroup_model.revoke_perm(id, 'hg.create.repository')
 
                usersgroup_model.grant_perm(id, 'hg.create.none')
 
                usergroup_model.revoke_perm(id, 'hg.create.repository')
 
                usergroup_model.grant_perm(id, 'hg.create.none')
 
                h.flash(_("Revoked 'repository create' permission to user group"),
 
                        category='success')
 

	
 
            if grant_fork_perm:
 
                usersgroup_model.revoke_perm(id, 'hg.fork.none')
 
                usersgroup_model.grant_perm(id, 'hg.fork.repository')
 
                usergroup_model.revoke_perm(id, 'hg.fork.none')
 
                usergroup_model.grant_perm(id, 'hg.fork.repository')
 
                h.flash(_("Granted 'repository fork' permission to user group"),
 
                        category='success')
 
            else:
 
                usersgroup_model.revoke_perm(id, 'hg.fork.repository')
 
                usersgroup_model.grant_perm(id, 'hg.fork.none')
 
                usergroup_model.revoke_perm(id, 'hg.fork.repository')
 
                usergroup_model.grant_perm(id, 'hg.fork.none')
 
                h.flash(_("Revoked 'repository fork' permission to user group"),
 
                        category='success')
 

	
 
            Session().commit()
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            h.flash(_('An error occurred during permissions saving'),
 
                    category='error')
 

	
 
        return redirect(url('edit_users_group', id=id))
rhodecode/controllers/api/api.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.controllers.api
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    API controller for RhodeCode
 

	
 
    :created_on: Aug 20, 2011
 
    :author: marcink
 
    :copyright: (C) 2011-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; version 2
 
# of the License or (at your opinion) any later version of the license.
 
#
 
# 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, write to the Free Software
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 
# MA  02110-1301, USA.
 

	
 
import traceback
 
import logging
 
from pylons.controllers.util import abort
 

	
 
from rhodecode.controllers.api import JSONRPCController, JSONRPCError
 
from rhodecode.lib.auth import PasswordGenerator, AuthUser, \
 
    HasPermissionAllDecorator, HasPermissionAnyDecorator, \
 
    HasPermissionAnyApi, HasRepoPermissionAnyApi
 
from rhodecode.lib.utils import map_groups, repo2db_mapper
 
from rhodecode.model.meta import Session
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.user import UserModel
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 
from rhodecode.model.permission import PermissionModel
 
from rhodecode.model.db import Repository, RhodeCodeSetting, UserIpMap
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class OptionalAttr(object):
 
    """
 
    Special Optional Option that defines other attribute
 
    """
 
    def __init__(self, attr_name):
 
        self.attr_name = attr_name
 

	
 
    def __repr__(self):
 
        return '<OptionalAttr:%s>' % self.attr_name
 

	
 
    def __call__(self):
 
        return self
 
#alias
 
OAttr = OptionalAttr
 

	
 

	
 
class Optional(object):
 
    """
 
    Defines an optional parameter::
 

	
 
        param = param.getval() if isinstance(param, Optional) else param
 
        param = param() if isinstance(param, Optional) else param
 

	
 
    is equivalent of::
 

	
 
        param = Optional.extract(param)
 

	
 
    """
 
    def __init__(self, type_):
 
        self.type_ = type_
 

	
 
    def __repr__(self):
 
        return '<Optional:%s>' % self.type_.__repr__()
 

	
 
    def __call__(self):
 
        return self.getval()
 

	
 
    def getval(self):
 
        """
 
        returns value from this Optional instance
 
        """
 
        return self.type_
 

	
 
    @classmethod
 
    def extract(cls, val):
 
        if isinstance(val, cls):
 
            return val.getval()
 
        return val
 

	
 

	
 
def get_user_or_error(userid):
 
    """
 
    Get user by id or name or return JsonRPCError if not found
 

	
 
    :param userid:
 
    """
 
    user = UserModel().get_user(userid)
 
    if user is None:
 
        raise JSONRPCError("user `%s` does not exist" % userid)
 
    return user
 

	
 

	
 
def get_repo_or_error(repoid):
 
    """
 
    Get repo by id or name or return JsonRPCError if not found
 

	
 
    :param userid:
 
    """
 
    repo = RepoModel().get_repo(repoid)
 
    if repo is None:
 
        raise JSONRPCError('repository `%s` does not exist' % (repoid))
 
    return repo
 

	
 

	
 
def get_users_group_or_error(usersgroupid):
 
    """
 
    Get user group by id or name or return JsonRPCError if not found
 

	
 
    :param userid:
 
    """
 
    users_group = UsersGroupModel().get_group(usersgroupid)
 
    users_group = UserGroupModel().get_group(usersgroupid)
 
    if users_group is None:
 
        raise JSONRPCError('user group `%s` does not exist' % usersgroupid)
 
    return users_group
 

	
 

	
 
def get_perm_or_error(permid):
 
    """
 
    Get permission by id or name or return JsonRPCError if not found
 

	
 
    :param userid:
 
    """
 
    perm = PermissionModel().get_permission_by_name(permid)
 
    if perm is None:
 
        raise JSONRPCError('permission `%s` does not exist' % (permid))
 
    return perm
 

	
 

	
 
class ApiController(JSONRPCController):
 
    """
 
    API Controller
 

	
 

	
 
    Each method needs to have USER as argument this is then based on given
 
    API_KEY propagated as instance of user object
 

	
 
    Preferably this should be first argument also
 

	
 

	
 
    Each function should also **raise** JSONRPCError for any
 
    errors that happens
 

	
 
    """
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def pull(self, apiuser, repoid):
 
        """
 
        Dispatch pull action on given repo
 

	
 
        :param apiuser:
 
        :param repoid:
 
        """
 

	
 
        repo = get_repo_or_error(repoid)
 

	
 
        try:
 
            ScmModel().pull_changes(repo.repo_name,
 
                                    self.rhodecode_user.username)
 
            return 'Pulled from `%s`' % repo.repo_name
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'Unable to pull changes from `%s`' % repo.repo_name
 
            )
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def rescan_repos(self, apiuser, remove_obsolete=Optional(False)):
 
        """
 
        Dispatch rescan repositories action. If remove_obsolete is set
 
        than also delete repos that are in database but not in the filesystem.
 
        aka "clean zombies"
 

	
 
        :param apiuser:
 
        :param remove_obsolete:
 
        """
 

	
 
        try:
 
            rm_obsolete = Optional.extract(remove_obsolete)
 
            added, removed = repo2db_mapper(ScmModel().repo_scan(),
 
                                            remove_obsolete=rm_obsolete)
 
            return {'added': added, 'removed': removed}
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'Error occurred during rescan repositories action'
 
            )
 

	
 
    def invalidate_cache(self, apiuser, repoid):
 
        """
 
        Dispatch cache invalidation action on given repo
 

	
 
        :param apiuser:
 
        :param repoid:
 
        """
 
        repo = get_repo_or_error(repoid)
 
        if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
 
            # check if we have admin permission for this repo !
 
            if HasRepoPermissionAnyApi('repository.admin',
 
                                       'repository.write')(user=apiuser,
 
                                            repo_name=repo.repo_name) is False:
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid))
 

	
 
        try:
 
            invalidated_keys = ScmModel().mark_for_invalidation(repo.repo_name)
 
            Session().commit()
 
            return ('Cache for repository `%s` was invalidated: '
 
                    'invalidated cache keys: %s' % (repoid, invalidated_keys))
 
@@ -381,268 +381,268 @@ class ApiController(JSONRPCController):
 
                    password=Optional(None)):
 
        """
 
        Updates given user
 

	
 
        :param apiuser:
 
        :param userid:
 
        :param username:
 
        :param email:
 
        :param firstname:
 
        :param lastname:
 
        :param active:
 
        :param admin:
 
        :param ldap_dn:
 
        :param password:
 
        """
 

	
 
        user = get_user_or_error(userid)
 

	
 
        # call function and store only updated arguments
 
        updates = {}
 

	
 
        def store_update(attr, name):
 
            if not isinstance(attr, Optional):
 
                updates[name] = attr
 

	
 
        try:
 

	
 
            store_update(username, 'username')
 
            store_update(password, 'password')
 
            store_update(email, 'email')
 
            store_update(firstname, 'name')
 
            store_update(lastname, 'lastname')
 
            store_update(active, 'active')
 
            store_update(admin, 'admin')
 
            store_update(ldap_dn, 'ldap_dn')
 

	
 
            user = UserModel().update_user(user, **updates)
 
            Session().commit()
 
            return dict(
 
                msg='updated user ID:%s %s' % (user.user_id, user.username),
 
                user=user.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to update user `%s`' % userid)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def delete_user(self, apiuser, userid):
 
        """"
 
        Deletes an user
 

	
 
        :param apiuser:
 
        :param userid:
 
        """
 
        user = get_user_or_error(userid)
 

	
 
        try:
 
            UserModel().delete(userid)
 
            Session().commit()
 
            return dict(
 
                msg='deleted user ID:%s %s' % (user.user_id, user.username),
 
                user=None
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to delete ID:%s %s' % (user.user_id,
 
                                                              user.username))
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def get_users_group(self, apiuser, usersgroupid):
 
        """"
 
        Get user group by name or id
 

	
 
        :param apiuser:
 
        :param usersgroupid:
 
        """
 
        users_group = get_users_group_or_error(usersgroupid)
 

	
 
        data = users_group.get_api_data()
 

	
 
        members = []
 
        for user in users_group.members:
 
            user = user.user
 
            members.append(user.get_api_data())
 
        data['members'] = members
 
        return data
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def get_users_groups(self, apiuser):
 
        """"
 
        Get all user groups
 

	
 
        :param apiuser:
 
        """
 

	
 
        result = []
 
        for users_group in UsersGroupModel().get_all():
 
        for users_group in UserGroupModel().get_all():
 
            result.append(users_group.get_api_data())
 
        return result
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_users_group(self, apiuser, group_name, active=Optional(True)):
 
        """
 
        Creates an new usergroup
 

	
 
        :param apiuser:
 
        :param group_name:
 
        :param active:
 
        """
 

	
 
        if UsersGroupModel().get_by_name(group_name):
 
        if UserGroupModel().get_by_name(group_name):
 
            raise JSONRPCError("user group `%s` already exist" % group_name)
 

	
 
        try:
 
            active = Optional.extract(active)
 
            ug = UsersGroupModel().create(name=group_name, active=active)
 
            ug = UserGroupModel().create(name=group_name, active=active)
 
            Session().commit()
 
            return dict(
 
                msg='created new user group `%s`' % group_name,
 
                users_group=ug.get_api_data()
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError('failed to create group `%s`' % group_name)
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def add_user_to_users_group(self, apiuser, usersgroupid, userid):
 
        """"
 
        Add a user to a user group
 

	
 
        :param apiuser:
 
        :param usersgroupid:
 
        :param userid:
 
        """
 
        user = get_user_or_error(userid)
 
        users_group = get_users_group_or_error(usersgroupid)
 

	
 
        try:
 
            ugm = UsersGroupModel().add_user_to_group(users_group, user)
 
            ugm = UserGroupModel().add_user_to_group(users_group, user)
 
            success = True if ugm != True else False
 
            msg = 'added member `%s` to user group `%s`' % (
 
                        user.username, users_group.users_group_name
 
                    )
 
            msg = msg if success else 'User is already in that group'
 
            Session().commit()
 

	
 
            return dict(
 
                success=success,
 
                msg=msg
 
            )
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to add member to user group `%s`' % (
 
                    users_group.users_group_name
 
                )
 
            )
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def remove_user_from_users_group(self, apiuser, usersgroupid, userid):
 
        """
 
        Remove user from a group
 

	
 
        :param apiuser:
 
        :param usersgroupid:
 
        :param userid:
 
        """
 
        user = get_user_or_error(userid)
 
        users_group = get_users_group_or_error(usersgroupid)
 

	
 
        try:
 
            success = UsersGroupModel().remove_user_from_group(users_group,
 
            success = UserGroupModel().remove_user_from_group(users_group,
 
                                                               user)
 
            msg = 'removed member `%s` from user group `%s`' % (
 
                        user.username, users_group.users_group_name
 
                    )
 
            msg = msg if success else "User wasn't in group"
 
            Session().commit()
 
            return dict(success=success, msg=msg)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise JSONRPCError(
 
                'failed to remove member from user group `%s`' % (
 
                        users_group.users_group_name
 
                    )
 
            )
 

	
 
    def get_repo(self, apiuser, repoid):
 
        """"
 
        Get repository by name
 

	
 
        :param apiuser:
 
        :param repoid:
 
        """
 
        repo = get_repo_or_error(repoid)
 

	
 
        if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
 
            # check if we have admin permission for this repo !
 
            if HasRepoPermissionAnyApi('repository.admin')(user=apiuser,
 
                                            repo_name=repo.repo_name) is False:
 
                raise JSONRPCError('repository `%s` does not exist' % (repoid))
 

	
 
        members = []
 
        followers = []
 
        for user in repo.repo_to_perm:
 
            perm = user.permission.permission_name
 
            user = user.user
 
            user_data = user.get_api_data()
 
            user_data['type'] = "user"
 
            user_data['permission'] = perm
 
            members.append(user_data)
 

	
 
        for users_group in repo.users_group_to_perm:
 
            perm = users_group.permission.permission_name
 
            users_group = users_group.users_group
 
            users_group_data = users_group.get_api_data()
 
            users_group_data['type'] = "users_group"
 
            users_group_data['permission'] = perm
 
            members.append(users_group_data)
 

	
 
        for user in repo.followers:
 
            followers.append(user.user.get_api_data())
 

	
 
        data = repo.get_api_data()
 
        data['members'] = members
 
        data['followers'] = followers
 
        return data
 

	
 
    def get_repos(self, apiuser):
 
        """"
 
        Get all repositories
 

	
 
        :param apiuser:
 
        """
 
        result = []
 
        if HasPermissionAnyApi('hg.admin')(user=apiuser) is False:
 
            repos = RepoModel().get_all_user_repos(user=apiuser)
 
        else:
 
            repos = RepoModel().get_all()
 

	
 
        for repo in repos:
 
            result.append(repo.get_api_data())
 
        return result
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def get_repo_nodes(self, apiuser, repoid, revision, root_path,
 
                       ret_type='all'):
 
        """
 
        returns a list of nodes and it's children
 
        for a given path at given revision. It's possible to specify ret_type
 
        to show only files or dirs
 

	
 
        :param apiuser:
 
        :param repoid: name or id of repository
 
        :param revision: revision for which listing should be done
 
        :param root_path: path from which start displaying
 
        :param ret_type: return type 'all|files|dirs' nodes
 
        """
 
        repo = get_repo_or_error(repoid)
 
        try:
 
            _d, _f = ScmModel().get_nodes(repo, revision, root_path,
 
                                          flat=False)
 
            _map = {
 
                'all': _d + _f,
 
                'files': _f,
 
                'dirs': _d,
 
            }
 
            return _map[ret_type]
rhodecode/lib/dbmigrate/schema/db_1_2_0.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.db_1_2_0
 
    ~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    Database Models for RhodeCode <=1.2.X
 

	
 
    :created_on: Apr 08, 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/>.
 

	
 
import os
 
import logging
 
import datetime
 
import traceback
 
from datetime import date
 

	
 
from sqlalchemy import *
 
from sqlalchemy.ext.hybrid import hybrid_property
 
from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
 
from beaker.cache import cache_region, region_invalidate
 

	
 
from rhodecode.lib.vcs import get_backend
 
from rhodecode.lib.vcs.utils.helpers import get_scm
 
from rhodecode.lib.vcs.exceptions import VCSError
 
from rhodecode.lib.vcs.utils.lazy import LazyProperty
 

	
 
from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
 
    generate_api_key, safe_unicode
 
from rhodecode.lib.exceptions import UsersGroupsAssignedException
 
from rhodecode.lib.exceptions import UserGroupsAssignedException
 
from rhodecode.lib.compat import json
 

	
 
from rhodecode.model.meta import Base, Session
 
from rhodecode.lib.caching_query import FromCache
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
#==============================================================================
 
# BASE CLASSES
 
#==============================================================================
 

	
 
class ModelSerializer(json.JSONEncoder):
 
    """
 
    Simple Serializer for JSON,
 

	
 
    usage::
 

	
 
        to make object customized for serialization implement a __json__
 
        method that will return a dict for serialization into json
 

	
 
    example::
 

	
 
        class Task(object):
 

	
 
            def __init__(self, name, value):
 
                self.name = name
 
                self.value = value
 

	
 
            def __json__(self):
 
                return dict(name=self.name,
 
                            value=self.value)
 

	
 
    """
 

	
 
    def default(self, obj):
 

	
 
        if hasattr(obj, '__json__'):
 
            return obj.__json__()
 
        else:
 
            return json.JSONEncoder.default(self, obj)
 

	
 
class BaseModel(object):
 
    """Base Model for all classess
 

	
 
    """
 

	
 
    @classmethod
 
    def _get_keys(cls):
 
        """return column names for this model """
 
        return class_mapper(cls).c.keys()
 

	
 
    def get_dict(self):
 
        """return dict with keys and values corresponding
 
        to this model data """
 

	
 
        d = {}
 
        for k in self._get_keys():
 
            d[k] = getattr(self, k)
 
        return d
 

	
 
    def get_appstruct(self):
 
        """return list with keys and values tupples corresponding
 
        to this model data """
 

	
 
        l = []
 
        for k in self._get_keys():
 
            l.append((k, getattr(self, k),))
 
        return l
 

	
 
    def populate_obj(self, populate_dict):
 
        """populate model with data from given populate_dict"""
 

	
 
        for k in self._get_keys():
 
            if k in populate_dict:
 
                setattr(self, k, populate_dict[k])
 

	
 
    @classmethod
 
    def query(cls):
 
        return Session.query(cls)
 

	
 
    @classmethod
 
    def get(cls, id_):
 
        if id_:
 
            return cls.query().get(id_)
 

	
 
    @classmethod
 
    def getAll(cls):
 
        return cls.query().all()
 

	
 
    @classmethod
 
    def delete(cls, id_):
 
        obj = cls.query().get(id_)
 
        Session.delete(obj)
 
        Session.commit()
 

	
 
@@ -189,416 +189,416 @@ class RhodeCodeSetting(Base, BaseModel):
 

	
 
        if cache:
 
            ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
 

	
 
        if not ret:
 
            raise Exception('Could not get application settings !')
 
        settings = {}
 
        for each in ret:
 
            settings['rhodecode_' + each.app_settings_name] = \
 
                each.app_settings_value
 

	
 
        return settings
 

	
 
    @classmethod
 
    def get_ldap_settings(cls, cache=False):
 
        ret = cls.query()\
 
                .filter(cls.app_settings_name.startswith('ldap_')).all()
 
        fd = {}
 
        for row in ret:
 
            fd.update({row.app_settings_name:row.app_settings_value})
 

	
 
        return fd
 

	
 

	
 
class RhodeCodeUi(Base, BaseModel):
 
    __tablename__ = 'rhodecode_ui'
 
    __table_args__ = (UniqueConstraint('ui_key'), {'extend_existing':True})
 

	
 
    HOOK_UPDATE = 'changegroup.update'
 
    HOOK_REPO_SIZE = 'changegroup.repo_size'
 
    HOOK_PUSH = 'pretxnchangegroup.push_logger'
 
    HOOK_PULL = 'preoutgoing.pull_logger'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.ui_key == key)
 

	
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
 
                                    cls.HOOK_REPO_SIZE,
 
                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
 
                                    cls.HOOK_REPO_SIZE,
 
                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
 
        q = q.filter(cls.ui_section == 'hooks')
 
        return q.all()
 

	
 
    @classmethod
 
    def create_or_update_hook(cls, key, val):
 
        new_ui = cls.get_by_key(key).scalar() or cls()
 
        new_ui.ui_section = 'hooks'
 
        new_ui.ui_active = True
 
        new_ui.ui_key = key
 
        new_ui.ui_value = val
 

	
 
        Session.add(new_ui)
 
        Session.commit()
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'extend_existing':True})
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=None)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    user_log = relationship('UserLog', cascade='all')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 
    group_member = relationship('UserGroupMember', cascade='all')
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.name, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    def __repr__(self):
 
        try:
 
            return "<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                             self.user_id, self.username)
 
        except:
 
            return self.__class__.__name__
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False):
 
        if case_insensitive:
 
            return Session.query(cls).filter(cls.username.ilike(username)).scalar()
 
        else:
 
            return Session.query(cls).filter(cls.username == username).scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key):
 
        return cls.query().filter(cls.api_key == api_key).one()
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 

	
 
        self.last_login = datetime.datetime.now()
 
        Session.add(self)
 
        Session.commit()
 
        log.debug('updated user %s lastlogin' % self.username)
 

	
 
    @classmethod
 
    def create(cls, form_data):
 
        from rhodecode.lib.auth import get_crypt_password
 

	
 
        try:
 
            new_user = cls()
 
            for k, v in form_data.items():
 
                if k == 'password':
 
                    v = get_crypt_password(v)
 
                setattr(new_user, k, v)
 

	
 
            new_user.api_key = generate_api_key(form_data['username'])
 
            Session.add(new_user)
 
            Session.commit()
 
            return new_user
 
        except:
 
            log.error(traceback.format_exc())
 
            Session.rollback()
 
            raise
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = {'extend_existing':True}
 
    user_log_id = Column("user_log_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)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 
    repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
class UserGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = {'extend_existing':True}
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 

	
 
    def __repr__(self):
 
        return '<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.users_group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache("sql_cache_short",
 
                                          "get_user_%s" % group_name))
 
        return gr.scalar()
 

	
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    @classmethod
 
    def create(cls, form_data):
 
        try:
 
            new_users_group = cls()
 
            for k, v in form_data.items():
 
                setattr(new_users_group, k, v)
 

	
 
            Session.add(new_users_group)
 
            Session.commit()
 
            return new_users_group
 
        except:
 
            log.error(traceback.format_exc())
 
            Session.rollback()
 
            raise
 

	
 
    @classmethod
 
    def update(cls, users_group_id, form_data):
 

	
 
        try:
 
            users_group = cls.get(users_group_id, cache=False)
 

	
 
            for k, v in form_data.items():
 
                if k == 'users_group_members':
 
                    users_group.members = []
 
                    Session.flush()
 
                    members_list = []
 
                    if v:
 
                        v = [v] if isinstance(v, basestring) else v
 
                        for u_id in set(v):
 
                            member = UsersGroupMember(users_group_id, u_id)
 
                            member = UserGroupMember(users_group_id, u_id)
 
                            members_list.append(member)
 
                    setattr(users_group, 'members', members_list)
 
                setattr(users_group, k, v)
 

	
 
            Session.add(users_group)
 
            Session.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            Session.rollback()
 
            raise
 

	
 
    @classmethod
 
    def delete(cls, users_group_id):
 
        try:
 

	
 
            # check if this group is not assigned to repo
 
            assigned_groups = UsersGroupRepoToPerm.query()\
 
                .filter(UsersGroupRepoToPerm.users_group_id ==
 
            assigned_groups = UserGroupRepoToPerm.query()\
 
                .filter(UserGroupRepoToPerm.users_group_id ==
 
                        users_group_id).all()
 

	
 
            if assigned_groups:
 
                raise UsersGroupsAssignedException('RepoGroup assigned to %s' %
 
                raise UserGroupsAssignedException('RepoGroup assigned to %s' %
 
                                                   assigned_groups)
 

	
 
            users_group = cls.get(users_group_id, cache=False)
 
            Session.delete(users_group)
 
            Session.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            Session.rollback()
 
            raise
 

	
 
class UsersGroupMember(Base, BaseModel):
 
class UserGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = {'extend_existing':True}
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 
    @staticmethod
 
    def add_user_to_group(group, user):
 
        ugm = UsersGroupMember()
 
        ugm = UserGroupMember()
 
        ugm.users_group = group
 
        ugm.user = user
 
        Session.add(ugm)
 
        Session.commit()
 
        return ugm
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},)
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
 

	
 
    logs = relationship('UserLog', cascade='all')
 

	
 
    def __repr__(self):
 
        return "<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.repo_id, self.repo_name)
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return '/'
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session.query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.one()
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              cls.url_sep())
 
        q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    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)
 

	
 
        return groups
 

	
 
    @property
 
    def groups_and_repo(self):
 
        return self.groups_with_parents, self.just_name
 

	
 
    @LazyProperty
 
    def repo_path(self):
 
        """
 
        Returns base full path for that repository means where it actually
 
        exists on a filesystem
 
        """
 
        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              Repository.url_sep())
 
        q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def repo_full_path(self):
 
        p = [self.repo_path]
 
        # we need to split the name by / since this is how we store the
 
        # names in the database, but that eventually needs to be converted
 
        # into a valid system path
 
        p += self.repo_name.split(Repository.url_sep())
 
        return os.path.join(*p)
 

	
 
    def get_new_name(self, repo_name):
 
        """
 
        returns new full repository name based on assigned group and new new
 

	
 
        :param group_name:
 
        """
 
        path_prefix = self.group.full_path_splitted if self.group else []
 
        return Repository.url_sep().join(path_prefix + [repo_name])
 

	
 
    @property
 
    def _ui(self):
 
        """
 
        Creates an db based ui object for this repository
 
@@ -816,215 +816,215 @@ class Group(Base, BaseModel):
 
    def repositories_recursive_count(self):
 
        cnt = self.repositories.count()
 

	
 
        def children_count(group):
 
            cnt = 0
 
            for child in group.children:
 
                cnt += child.repositories.count()
 
                cnt += children_count(child)
 
            return cnt
 

	
 
        return cnt + children_count(self)
 

	
 

	
 
    def get_new_name(self, group_name):
 
        """
 
        returns new full group name based on parent and new name
 

	
 
        :param group_name:
 
        """
 
        path_prefix = (self.parent_group.full_path_splitted if
 
                       self.parent_group else [])
 
        return Group.url_sep().join(path_prefix + [group_name])
 

	
 

	
 
class Permission(Base, BaseModel):
 
    __tablename__ = 'permissions'
 
    __table_args__ = {'extend_existing':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)
 

	
 
    def __repr__(self):
 
        return "<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.permission_id, self.permission_name)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'repository_id'), {'extend_existing':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, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (UniqueConstraint('user_id', 'permission_id'), {'extend_existing':True})
 
    user_to_perm_id = Column("user_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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def has_perm(cls, user_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        return cls.query().filter(cls.user_id == user_id)\
 
            .filter(cls.permission == perm).scalar() is not None
 

	
 
    @classmethod
 
    def grant_perm(cls, user_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        new = cls()
 
        new.user_id = user_id
 
        new.permission = perm
 
        try:
 
            Session.add(new)
 
            Session.commit()
 
        except:
 
            Session.rollback()
 

	
 

	
 
    @classmethod
 
    def revoke_perm(cls, user_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        try:
 
            cls.query().filter(cls.user_id == user_id)\
 
                .filter(cls.permission == perm).delete()
 
            Session.commit()
 
        except:
 
            Session.rollback()
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
class UserGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (UniqueConstraint('repository_id', 'users_group_id', 'permission_id'), {'extend_existing':True})
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_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)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    def __repr__(self):
 
        return '<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
class UserGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = {'extend_existing':True}
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
    @classmethod
 
    def has_perm(cls, users_group_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        return cls.query().filter(cls.users_group_id ==
 
                                         users_group_id)\
 
                                         .filter(cls.permission == perm)\
 
                                         .scalar() is not None
 

	
 
    @classmethod
 
    def grant_perm(cls, users_group_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        new = cls()
 
        new.users_group_id = users_group_id
 
        new.permission = perm
 
        try:
 
            Session.add(new)
 
            Session.commit()
 
        except:
 
            Session.rollback()
 

	
 

	
 
    @classmethod
 
    def revoke_perm(cls, users_group_id, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class')
 

	
 
        try:
 
            cls.query().filter(cls.users_group_id == users_group_id)\
 
                .filter(cls.permission == perm).delete()
 
            Session.commit()
 
        except:
 
            Session.rollback()
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'group_to_perm'
 
    __table_args__ = (UniqueConstraint('group_id', 'permission_id'), {'extend_existing':True})
 

	
 
    group_to_perm_id = Column("group_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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (UniqueConstraint('repository_id'), {'extend_existing':True})
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (UniqueConstraint('user_id', 'follows_repository_id'),
 
                      UniqueConstraint('user_id', 'follows_user_id')
 
                      , {'extend_existing':True})
 

	
 
    user_following_id = Column("user_following_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)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (UniqueConstraint('cache_key'), {'extend_existing':True})
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
rhodecode/lib/dbmigrate/schema/db_1_3_0.py
Show inline comments
 
@@ -212,398 +212,398 @@ class RhodeCodeSetting(Base, BaseModel):
 
        settings = {}
 
        for each in ret:
 
            settings['rhodecode_' + each.app_settings_name] = \
 
                each.app_settings_value
 

	
 
        return settings
 

	
 
    @classmethod
 
    def get_ldap_settings(cls, cache=False):
 
        ret = cls.query()\
 
                .filter(cls.app_settings_name.startswith('ldap_')).all()
 
        fd = {}
 
        for row in ret:
 
            fd.update({row.app_settings_name:row.app_settings_value})
 

	
 
        return fd
 

	
 

	
 
class RhodeCodeUi(Base, BaseModel):
 
    __tablename__ = 'rhodecode_ui'
 
    __table_args__ = (
 
        UniqueConstraint('ui_key'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    HOOK_UPDATE = 'changegroup.update'
 
    HOOK_REPO_SIZE = 'changegroup.repo_size'
 
    HOOK_PUSH = 'pretxnchangegroup.push_logger'
 
    HOOK_PULL = 'preoutgoing.pull_logger'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.ui_key == key)
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE,
 
                                    cls.HOOK_REPO_SIZE,
 
                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE,
 
                                    cls.HOOK_REPO_SIZE,
 
                                    cls.HOOK_PUSH, cls.HOOK_PULL]))
 
        q = q.filter(cls.ui_section == 'hooks')
 
        return q.all()
 

	
 
    @classmethod
 
    def create_or_update_hook(cls, key, val):
 
        new_ui = cls.get_by_key(key).scalar() or cls()
 
        new_ui.ui_section = 'hooks'
 
        new_ui.ui_active = True
 
        new_ui.ui_key = key
 
        new_ui.ui_value = val
 

	
 
        Session.add(new_ui)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (
 
        UniqueConstraint('username'), UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=None)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    user_log = relationship('UserLog', cascade='all')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 
    group_member = relationship('UserGroupMember', cascade='all')
 

	
 
    notifications = relationship('UserNotification', cascade='all')
 
    # notifications assigned to this user
 
    user_created_notifications = relationship('Notification', cascade='all')
 
    # comments created by this user
 
    user_comments = relationship('ChangesetComment', cascade='all')
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 
    @property
 
    def full_name(self):
 
        return '%s %s' % (self.name, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.name, self.lastname)
 
                if (self.name and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.name, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    def __unicode__(self):
 
        return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                     self.user_id, self.username)
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.email.ilike(email))
 
        else:
 
            q = cls.query().filter(cls.email == email)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % email))
 
        return q.scalar()
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 
        self.last_login = datetime.datetime.now()
 
        Session.add(self)
 
        log.debug('updated user %s lastlogin' % self.username)
 

	
 
    def __json__(self):
 
        return dict(
 
            user_id=self.user_id,
 
            first_name=self.name,
 
            last_name=self.lastname,
 
            email=self.email,
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    user_log_id = Column("user_log_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)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
 
    repository_name = Column("repository_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(length=1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository', cascade='')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
class UserGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
class UserGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(length=255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default='hg')
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(length=10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id', cascade='all')
 

	
 
    logs = relationship('UserLog')
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,self.repo_id,
 
                                   self.repo_name)
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return '/'
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session.query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session.query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    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)
 

	
 
        return groups
 

	
 
    @property
 
    def groups_and_repo(self):
 
        return self.groups_with_parents, self.just_name
 

	
 
    @LazyProperty
 
    def repo_path(self):
 
        """
 
        Returns base full path for that repository means where it actually
 
        exists on a filesystem
 
        """
 
        q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
 
                                              Repository.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def repo_full_path(self):
 
        p = [self.repo_path]
 
        # we need to split the name by / since this is how we store the
 
        # names in the database, but that eventually needs to be converted
 
        # into a valid system path
 
        p += self.repo_name.split(Repository.url_sep())
 
        return os.path.join(*p)
 

	
 
    def get_new_name(self, repo_name):
 
        """
 
        returns new full repository name based on assigned group and new new
 

	
 
        :param group_name:
 
        """
 
        path_prefix = self.group.full_path_splitted if self.group else []
 
        return Repository.url_sep().join(path_prefix + [repo_name])
 

	
 
    @property
 
    def _ui(self):
 
        """
 
        Creates an db based ui object for this repository
 
@@ -656,193 +656,193 @@ class Repository(Base, BaseModel):
 
    def author(self):
 
        return self.tip.author
 

	
 
    @property
 
    def last_change(self):
 
        return self.scm_instance.last_change
 

	
 
    def comments(self, revisions=None):
 
        """
 
        Returns comments for this repository grouped by revisions
 

	
 
        :param revisions: filter query by revisions only
 
        """
 
        cmts = ChangesetComment.query()\
 
            .filter(ChangesetComment.repo == self)
 
        if revisions:
 
            cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
 
        grouped = defaultdict(list)
 
        for cmt in cmts.all():
 
            grouped[cmt.revision].append(cmt)
 
        return grouped
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        return self.__get_instance()
 

	
 
    @property
 
    def scm_instance_cached(self):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 
        inv = self.invalidate
 
        if inv is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(inv.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository' % alias)
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    __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)
 

	
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
 

	
 
    parent_group = relationship('RepoGroup', remote_side=group_id)
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @classmethod
 
    def groups_choices(cls):
 
        from webhelpers.html import literal as _literal
 
        repo_groups = [('', '')]
 
        sep = ' &raquo; '
 
        _name = lambda k: _literal(sep.join(k))
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in cls.query().all()])
 

	
 
        repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
 
        return repo_groups
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return '/'
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_group_%s" % _hash_key(group_name)
 
                            )
 
            )
 
        return gr.scalar()
 

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return RepoGroup.query().filter(RepoGroup.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(RepoGroup.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query()\
 
                .filter(Repository.group == self)\
 
                .order_by(Repository.repo_name)
 

	
 
    @property
 
    def repositories_recursive_count(self):
 
        cnt = self.repositories.count()
 

	
 
        def children_count(group):
 
            cnt = 0
 
@@ -853,268 +853,268 @@ class RepoGroup(Base, BaseModel):
 

	
 
        return cnt + children_count(self)
 

	
 
    def get_new_name(self, group_name):
 
        """
 
        returns new full group name based on parent and new name
 

	
 
        :param group_name:
 
        """
 
        path_prefix = (self.parent_group.full_path_splitted if
 
                       self.parent_group else [])
 
        return RepoGroup.url_sep().join(path_prefix + [group_name])
 

	
 

	
 
class Permission(Base, BaseModel):
 
    __tablename__ = 'permissions'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    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)
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__, self.permission_id, self.permission_name
 
        )
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session.query(UserRepoToPerm, Repository, cls)\
 
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session.query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    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')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session.add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_to_perm_id = Column("user_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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
class UserGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_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)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session.add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
class UserGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    group_to_perm_id = Column("group_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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
class UserGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (
 
         UniqueConstraint('repository_id'),
 
         {'extend_existing': True, 'mysql_engine':'InnoDB',
 
          'mysql_charset': 'utf8'}
 
    )
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'follows_repository_id'),
 
        UniqueConstraint('user_id', 'follows_user_id'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    user_following_id = Column("user_following_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)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (
 
        UniqueConstraint('cache_key'),
 
        {'extend_existing': True, 'mysql_engine':'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.cache_id, self.cache_key)
 
    @classmethod
 
    def clear_cache(cls):
 
        cls.query().delete()
 

	
 
    @classmethod
 
    def _get_key(cls, key):
 
        """
 
        Wrapper for generating a key, together with a prefix
 

	
 
        :param key:
 
        """
 
        import rhodecode
 
        prefix = ''
 
        iid = rhodecode.CONFIG.get('instance_id')
 
        if iid:
 
            prefix = iid
 
        return "%s%s" % (prefix, key), prefix, key.rstrip('_README')
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.cache_key == key).scalar()
 

	
 
    @classmethod
 
    def _get_or_create_key(cls, key, prefix, org_key):
 
        inv_obj = Session.query(cls).filter(cls.cache_key == key).scalar()
 
        if not inv_obj:
 
            try:
 
                inv_obj = CacheInvalidation(key, org_key)
 
                Session.add(inv_obj)
 
                Session.commit()
rhodecode/lib/dbmigrate/schema/db_1_4_0.py
Show inline comments
 
@@ -229,193 +229,193 @@ class RhodeCodeSetting(Base, BaseModel):
 
class RhodeCodeUi(Base, BaseModel):
 
    __tablename__ = 'rhodecode_ui'
 
    __table_args__ = (
 
        UniqueConstraint('ui_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    HOOK_UPDATE = 'changegroup.update'
 
    HOOK_REPO_SIZE = 'changegroup.repo_size'
 
    HOOK_PUSH = 'changegroup.push_logger'
 
    HOOK_PRE_PUSH = 'prechangegroup.pre_push'
 
    HOOK_PULL = 'outgoing.pull_logger'
 
    HOOK_PRE_PULL = 'preoutgoing.pre_pull'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.ui_key == key).scalar()
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                     cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                     cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                      cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                      cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        q = q.filter(cls.ui_section == 'hooks')
 
        return q.all()
 

	
 
    @classmethod
 
    def get_repos_location(cls):
 
        return cls.get_by_key('/').ui_value
 

	
 
    @classmethod
 
    def create_or_update_hook(cls, key, val):
 
        new_ui = cls.get_by_key(key) or cls()
 
        new_ui.ui_section = 'hooks'
 
        new_ui.ui_active = True
 
        new_ui.ui_key = key
 
        new_ui.ui_value = val
 

	
 
        Session().add(new_ui)
 

	
 
    def __repr__(self):
 
        return '<DB:%s[%s:%s]>' % (self.__class__.__name__, self.ui_key,
 
                                   self.ui_value)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (
 
        UniqueConstraint('username'), UniqueConstraint('email'),
 
        Index('u_username_idx', 'username'),
 
        Index('u_email_idx', 'email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    DEFAULT_USER = 'default'
 
    DEFAULT_PERMISSIONS = [
 
        'hg.register.manual_activate', 'hg.create.repository',
 
        'hg.fork.repository', 'repository.read', 'group.read'
 
    ]
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    user_log = relationship('UserLog', cascade='all')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 
    group_member = relationship('UserGroupMember', cascade='all')
 

	
 
    notifications = relationship('UserNotification', cascade='all')
 
    # notifications assigned to this user
 
    user_created_notifications = relationship('Notification', cascade='all')
 
    # comments created by this user
 
    user_comments = relationship('ChangesetComment', cascade='all')
 
    #extra emails for this user
 
    user_emails = relationship('UserEmailMap', cascade='all')
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 
    @property
 
    def firstname(self):
 
        # alias for future
 
        return self.name
 

	
 
    @property
 
    def emails(self):
 
        other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
 
        return [self.email] + [x.email for x in other]
 

	
 
    @property
 
    def username_and_name(self):
 
        return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.firstname, self.lastname)
 
                if (self.firstname and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    def __unicode__(self):
 
        return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                     self.user_id, self.username)
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.email.ilike(email))
 
        else:
 
            q = cls.query().filter(cls.email == email)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_email_key_%s" % email))
 

	
 
        ret = q.scalar()
 
        if ret is None:
 
            q = UserEmailMap.query()
 
            # try fetching in alternate email map
 
            if case_insensitive:
 
@@ -428,297 +428,297 @@ class User(Base, BaseModel):
 
                                        "get_email_map_key_%s" % email))
 
            ret = getattr(q.scalar(), 'user', None)
 

	
 
        return ret
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 
        self.last_login = datetime.datetime.now()
 
        Session().add(self)
 
        log.debug('updated user %s lastlogin' % self.username)
 

	
 
    def get_api_data(self):
 
        """
 
        Common function for generating user related data for API
 
        """
 
        user = self
 
        data = dict(
 
            user_id=user.user_id,
 
            username=user.username,
 
            firstname=user.name,
 
            lastname=user.lastname,
 
            email=user.email,
 
            emails=user.emails,
 
            api_key=user.api_key,
 
            active=user.active,
 
            admin=user.admin,
 
            ldap_dn=user.ldap_dn,
 
            last_login=user.last_login,
 
        )
 
        return data
 

	
 
    def __json__(self):
 
        data = dict(
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 
        data.update(self.get_api_data())
 
        return data
 

	
 

	
 
class UserEmailMap(Base, BaseModel):
 
    __tablename__ = 'user_email_map'
 
    __table_args__ = (
 
        Index('uem_email_idx', 'email'),
 
        UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    user = relationship('User', lazy='joined')
 

	
 
    @validates('_email')
 
    def validate_email(self, key, email):
 
        # check if this email is not main one
 
        main_email = Session().query(User).filter(User.email == email).scalar()
 
        if main_email is not None:
 
            raise AttributeError('email %s is present is user table' % email)
 
        return email
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    user_log_id = Column("user_log_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)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
 
    repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository', cascade='')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
class UserGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    def get_api_data(self):
 
        users_group = self
 

	
 
        data = dict(
 
            users_group_id=users_group.users_group_id,
 
            group_name=users_group.users_group_name,
 
            active=users_group.users_group_active,
 
        )
 

	
 
        return data
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
class UserGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        Index('r_repo_name_idx', 'repo_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
    _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing',
 
                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
 
                             cascade='all')
 

	
 
    logs = relationship('UserLog')
 
    comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_org = relationship('PullRequest',
 
                    primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_other = relationship('PullRequest',
 
                    primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
 
                                   self.repo_name)
 

	
 
    @hybrid_property
 
    def locked(self):
 
        # always should return [user_id, timelocked]
 
        if self._locked:
 
            _lock_info = self._locked.split(':')
 
            return int(_lock_info[0]), _lock_info[1]
 
        return [None, None]
 

	
 
    @locked.setter
 
    def locked(self, val):
 
        if val and isinstance(val, (list, tuple)):
 
            self._locked = ':'.join(map(str, val))
 
        else:
 
            self._locked = None
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_full_path(cls, repo_full_path):
 
        repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
 
        return cls.get_by_repo_name(repo_name.strip(URL_SEP))
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session().query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def forks(self):
 
        """
 
        Return forks of this repo
 
        """
 
        return Repository.get_repo_forks(self.repo_id)
 

	
 
    @property
 
    def parent(self):
 
        """
 
        Returns fork parent
 
        """
 
        return self.fork
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    def groups_with_parents(self):
 
        groups = []
 
        if self.group is None:
 
            return groups
 

	
 
        cur_gr = self.group
 
        groups.insert(0, cur_gr)
 
        while 1:
 
@@ -920,193 +920,193 @@ class Repository(Base, BaseModel):
 
            pr_id = pr_repo = None
 
            if stat.pull_request:
 
                pr_id = stat.pull_request.pull_request_id
 
                pr_repo = stat.pull_request.other_repo.repo_name
 
            grouped[stat.revision] = [str(stat.status), stat.status_lbl,
 
                                      pr_id, pr_repo]
 
        return grouped
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(repo_name=self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        import rhodecode
 
        full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, cache_map=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 

	
 
        if cache_map:
 
            # get using prefilled cache_map
 
            invalidate_repo = cache_map[self.repo_name]
 
            if invalidate_repo:
 
                invalidate_repo = (None if invalidate_repo.cache_active
 
                                   else invalidate_repo)
 
        else:
 
            # get from invalidate
 
            invalidate_repo = self.invalidate
 

	
 
        if invalidate_repo is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(invalidate_repo.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository' % alias)
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    __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(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(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
 

	
 
    parent_group = relationship('RepoGroup', remote_side=group_id)
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @classmethod
 
    def groups_choices(cls, check_perms=False):
 
        from webhelpers.html import literal as _literal
 
        from rhodecode.model.scm import ScmModel
 
        groups = cls.query().all()
 
        if check_perms:
 
            #filter group user have access to, it's done
 
            #magically inside ScmModel based on current user
 
            groups = ScmModel().get_repos_groups(groups)
 
        repo_groups = [('', '')]
 
        sep = ' &raquo; '
 
        _name = lambda k: _literal(sep.join(k))
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in groups])
 

	
 
        repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
 
        return repo_groups
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_group_%s" % _hash_key(group_name)
 
                            )
 
            )
 
        return gr.scalar()
 

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return RepoGroup.query().filter(RepoGroup.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(RepoGroup.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query()\
 
                .filter(Repository.group == self)\
 
                .order_by(Repository.repo_name)
 

	
 
@@ -1184,268 +1184,268 @@ class Permission(Base, BaseModel):
 
    ]
 

	
 
    # defines which permissions are more important higher the more important
 
    PERM_WEIGHTS = {
 
        'repository.none': 0,
 
        'repository.read': 1,
 
        'repository.write': 3,
 
        'repository.admin': 4,
 

	
 
        'group.none': 0,
 
        'group.read': 1,
 
        'group.write': 3,
 
        'group.admin': 4,
 

	
 
        'hg.fork.none': 0,
 
        'hg.fork.repository': 1,
 
        'hg.create.none': 0,
 
        'hg.create.repository':1
 
    }
 

	
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__, self.permission_id, self.permission_name
 
        )
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session().query(UserRepoToPerm, Repository, cls)\
 
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    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')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_to_perm_id = Column("user_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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
class UserGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_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)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
class UserGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    group_to_perm_id = Column("group_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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
class UserGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (
 
         UniqueConstraint('repository_id'),
 
         {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
          'mysql_charset': 'utf8'}
 
    )
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'follows_repository_id'),
 
        UniqueConstraint('user_id', 'follows_user_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    user_following_id = Column("user_following_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)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (
 
        UniqueConstraint('cache_key'),
 
        Index('key_idx', 'cache_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.cache_id, self.cache_key)
 

	
 
    @property
 
    def prefix(self):
 
        _split = self.cache_key.split(self.cache_args, 1)
 
        if _split and len(_split) == 2:
 
            return _split[0]
 
        return ''
 

	
 
    @classmethod
 
    def clear_cache(cls):
 
        cls.query().delete()
 

	
 
    @classmethod
 
    def _get_key(cls, key):
 
        """
 
        Wrapper for generating a key, together with a prefix
 

	
 
        :param key:
 
        """
 
        import rhodecode
 
        prefix = ''
 
        org_key = key
 
        iid = rhodecode.CONFIG.get('instance_id')
 
        if iid:
 
            prefix = iid
 

	
 
        return "%s%s" % (prefix, key), prefix, org_key
 

	
 
    @classmethod
rhodecode/lib/dbmigrate/schema/db_1_5_0.py
Show inline comments
 
@@ -248,193 +248,193 @@ class RhodeCodeUi(Base, BaseModel):
 
    __table_args__ = (
 
        UniqueConstraint('ui_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    HOOK_UPDATE = 'changegroup.update'
 
    HOOK_REPO_SIZE = 'changegroup.repo_size'
 
    HOOK_PUSH = 'changegroup.push_logger'
 
    HOOK_PRE_PUSH = 'prechangegroup.pre_push'
 
    HOOK_PULL = 'outgoing.pull_logger'
 
    HOOK_PRE_PULL = 'preoutgoing.pre_pull'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.ui_key == key).scalar()
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                     cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                     cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                      cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                      cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        q = q.filter(cls.ui_section == 'hooks')
 
        return q.all()
 

	
 
    @classmethod
 
    def get_repos_location(cls):
 
        return cls.get_by_key('/').ui_value
 

	
 
    @classmethod
 
    def create_or_update_hook(cls, key, val):
 
        new_ui = cls.get_by_key(key) or cls()
 
        new_ui.ui_section = 'hooks'
 
        new_ui.ui_active = True
 
        new_ui.ui_key = key
 
        new_ui.ui_value = val
 

	
 
        Session().add(new_ui)
 

	
 
    def __repr__(self):
 
        return '<DB:%s[%s:%s]>' % (self.__class__.__name__, self.ui_key,
 
                                   self.ui_value)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (
 
        UniqueConstraint('username'), UniqueConstraint('email'),
 
        Index('u_username_idx', 'username'),
 
        Index('u_email_idx', 'email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    DEFAULT_USER = 'default'
 
    DEFAULT_PERMISSIONS = [
 
        'hg.register.manual_activate', 'hg.create.repository',
 
        'hg.fork.repository', 'repository.read', 'group.read'
 
    ]
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    user_log = relationship('UserLog')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
 

	
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 
    group_member = relationship('UserGroupMember', cascade='all')
 

	
 
    notifications = relationship('UserNotification', cascade='all')
 
    # notifications assigned to this user
 
    user_created_notifications = relationship('Notification', cascade='all')
 
    # comments created by this user
 
    user_comments = relationship('ChangesetComment', cascade='all')
 
    #extra emails for this user
 
    user_emails = relationship('UserEmailMap', cascade='all')
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 
    @property
 
    def firstname(self):
 
        # alias for future
 
        return self.name
 

	
 
    @property
 
    def emails(self):
 
        other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
 
        return [self.email] + [x.email for x in other]
 

	
 
    @property
 
    def username_and_name(self):
 
        return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.firstname, self.lastname)
 
                if (self.firstname and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    def __unicode__(self):
 
        return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                     self.user_id, self.username)
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.email.ilike(email))
 
        else:
 
            q = cls.query().filter(cls.email == email)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_email_key_%s" % email))
 

	
 
        ret = q.scalar()
 
        if ret is None:
 
            q = UserEmailMap.query()
 
            # try fetching in alternate email map
 
            if case_insensitive:
 
@@ -448,297 +448,297 @@ class User(Base, BaseModel):
 
            ret = getattr(q.scalar(), 'user', None)
 

	
 
        return ret
 

	
 
    def update_lastlogin(self):
 
        """Update user lastlogin"""
 
        self.last_login = datetime.datetime.now()
 
        Session().add(self)
 
        log.debug('updated user %s lastlogin' % self.username)
 

	
 
    def get_api_data(self):
 
        """
 
        Common function for generating user related data for API
 
        """
 
        user = self
 
        data = dict(
 
            user_id=user.user_id,
 
            username=user.username,
 
            firstname=user.name,
 
            lastname=user.lastname,
 
            email=user.email,
 
            emails=user.emails,
 
            api_key=user.api_key,
 
            active=user.active,
 
            admin=user.admin,
 
            ldap_dn=user.ldap_dn,
 
            last_login=user.last_login,
 
        )
 
        return data
 

	
 
    def __json__(self):
 
        data = dict(
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 
        data.update(self.get_api_data())
 
        return data
 

	
 

	
 
class UserEmailMap(Base, BaseModel):
 
    __tablename__ = 'user_email_map'
 
    __table_args__ = (
 
        Index('uem_email_idx', 'email'),
 
        UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    user = relationship('User', lazy='joined')
 

	
 
    @validates('_email')
 
    def validate_email(self, key, email):
 
        # check if this email is not main one
 
        main_email = Session().query(User).filter(User.email == email).scalar()
 
        if main_email is not None:
 
            raise AttributeError('email %s is present is user table' % email)
 
        return email
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
 
    repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository', cascade='')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
class UserGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    def get_api_data(self):
 
        users_group = self
 

	
 
        data = dict(
 
            users_group_id=users_group.users_group_id,
 
            group_name=users_group.users_group_name,
 
            active=users_group.users_group_active,
 
        )
 

	
 
        return data
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
class UserGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        Index('r_repo_name_idx', 'repo_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
    _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing',
 
                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
 
                             cascade='all')
 

	
 
    logs = relationship('UserLog')
 
    comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_org = relationship('PullRequest',
 
                    primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_other = relationship('PullRequest',
 
                    primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
 
                                   self.repo_name)
 

	
 
    @hybrid_property
 
    def locked(self):
 
        # always should return [user_id, timelocked]
 
        if self._locked:
 
            _lock_info = self._locked.split(':')
 
            return int(_lock_info[0]), _lock_info[1]
 
        return [None, None]
 

	
 
    @locked.setter
 
    def locked(self, val):
 
        if val and isinstance(val, (list, tuple)):
 
            self._locked = ':'.join(map(str, val))
 
        else:
 
            self._locked = None
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_full_path(cls, repo_full_path):
 
        repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
 
        return cls.get_by_repo_name(repo_name.strip(URL_SEP))
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session().query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
        q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
 
        return q.one().ui_value
 

	
 
    @property
 
    def forks(self):
 
        """
 
        Return forks of this repo
 
        """
 
        return Repository.get_repo_forks(self.repo_id)
 

	
 
    @property
 
    def parent(self):
 
        """
 
        Returns fork parent
 
        """
 
        return self.fork
 

	
 
    @property
 
    def just_name(self):
 
        return self.repo_name.split(Repository.url_sep())[-1]
 

	
 
    @property
 
    def groups_with_parents(self):
 
        groups = []
 
        if self.group is None:
 
            return groups
 

	
 
        cur_gr = self.group
 
        groups.insert(0, cur_gr)
 
        while 1:
 
@@ -940,193 +940,193 @@ class Repository(Base, BaseModel):
 
            pr_id = pr_repo = None
 
            if stat.pull_request:
 
                pr_id = stat.pull_request.pull_request_id
 
                pr_repo = stat.pull_request.other_repo.repo_name
 
            grouped[stat.revision] = [str(stat.status), stat.status_lbl,
 
                                      pr_id, pr_repo]
 
        return grouped
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(repo_name=self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        import rhodecode
 
        full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, cache_map=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 

	
 
        if cache_map:
 
            # get using prefilled cache_map
 
            invalidate_repo = cache_map[self.repo_name]
 
            if invalidate_repo:
 
                invalidate_repo = (None if invalidate_repo.cache_active
 
                                   else invalidate_repo)
 
        else:
 
            # get from invalidate
 
            invalidate_repo = self.invalidate
 

	
 
        if invalidate_repo is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(invalidate_repo.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository' % alias)
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    __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(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(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
 

	
 
    parent_group = relationship('RepoGroup', remote_side=group_id)
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @classmethod
 
    def groups_choices(cls, check_perms=False):
 
        from webhelpers.html import literal as _literal
 
        from rhodecode.model.scm import ScmModel
 
        groups = cls.query().all()
 
        if check_perms:
 
            #filter group user have access to, it's done
 
            #magically inside ScmModel based on current user
 
            groups = ScmModel().get_repos_groups(groups)
 
        repo_groups = [('', '')]
 
        sep = ' &raquo; '
 
        _name = lambda k: _literal(sep.join(k))
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in groups])
 

	
 
        repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
 
        return repo_groups
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_group_%s" % _hash_key(group_name)
 
                            )
 
            )
 
        return gr.scalar()
 

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return RepoGroup.query().filter(RepoGroup.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(RepoGroup.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query()\
 
                .filter(Repository.group == self)\
 
                .order_by(Repository.repo_name)
 

	
 
@@ -1204,268 +1204,268 @@ class Permission(Base, BaseModel):
 
    ]
 

	
 
    # defines which permissions are more important higher the more important
 
    PERM_WEIGHTS = {
 
        'repository.none': 0,
 
        'repository.read': 1,
 
        'repository.write': 3,
 
        'repository.admin': 4,
 

	
 
        'group.none': 0,
 
        'group.read': 1,
 
        'group.write': 3,
 
        'group.admin': 4,
 

	
 
        'hg.fork.none': 0,
 
        'hg.fork.repository': 1,
 
        'hg.create.none': 0,
 
        'hg.create.repository':1
 
    }
 

	
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__, self.permission_id, self.permission_name
 
        )
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session().query(UserRepoToPerm, Repository, cls)\
 
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    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')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_to_perm_id = Column("user_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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
class UserGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_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)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
class UserGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    group_to_perm_id = Column("group_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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
class UserGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (
 
         UniqueConstraint('repository_id'),
 
         {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
          'mysql_charset': 'utf8'}
 
    )
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'follows_repository_id'),
 
        UniqueConstraint('user_id', 'follows_user_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    user_following_id = Column("user_following_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)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (
 
        UniqueConstraint('cache_key'),
 
        Index('key_idx', 'cache_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.cache_id, self.cache_key)
 

	
 
    @property
 
    def prefix(self):
 
        _split = self.cache_key.split(self.cache_args, 1)
 
        if _split and len(_split) == 2:
 
            return _split[0]
 
        return ''
 

	
 
    @classmethod
 
    def clear_cache(cls):
 
        cls.query().delete()
 

	
 
    @classmethod
 
    def _get_key(cls, key):
 
        """
 
        Wrapper for generating a key, together with a prefix
 

	
 
        :param key:
 
        """
 
        import rhodecode
 
        prefix = ''
 
        org_key = key
 
        iid = rhodecode.CONFIG.get('instance_id')
 
        if iid:
 
            prefix = iid
 

	
 
        return "%s%s" % (prefix, key), prefix, org_key
 

	
 
    @classmethod
rhodecode/lib/dbmigrate/schema/db_1_5_2.py
Show inline comments
 
@@ -248,193 +248,193 @@ class RhodeCodeUi(Base, BaseModel):
 
    __table_args__ = (
 
        UniqueConstraint('ui_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    HOOK_UPDATE = 'changegroup.update'
 
    HOOK_REPO_SIZE = 'changegroup.repo_size'
 
    HOOK_PUSH = 'changegroup.push_logger'
 
    HOOK_PRE_PUSH = 'prechangegroup.pre_push'
 
    HOOK_PULL = 'outgoing.pull_logger'
 
    HOOK_PRE_PULL = 'preoutgoing.pre_pull'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.ui_key == key).scalar()
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                     cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                     cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                      cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                      cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        q = q.filter(cls.ui_section == 'hooks')
 
        return q.all()
 

	
 
    @classmethod
 
    def get_repos_location(cls):
 
        return cls.get_by_key('/').ui_value
 

	
 
    @classmethod
 
    def create_or_update_hook(cls, key, val):
 
        new_ui = cls.get_by_key(key) or cls()
 
        new_ui.ui_section = 'hooks'
 
        new_ui.ui_active = True
 
        new_ui.ui_key = key
 
        new_ui.ui_value = val
 

	
 
        Session().add(new_ui)
 

	
 
    def __repr__(self):
 
        return '<DB:%s[%s:%s]>' % (self.__class__.__name__, self.ui_key,
 
                                   self.ui_value)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (
 
        UniqueConstraint('username'), UniqueConstraint('email'),
 
        Index('u_username_idx', 'username'),
 
        Index('u_email_idx', 'email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    DEFAULT_USER = 'default'
 
    DEFAULT_PERMISSIONS = [
 
        'hg.register.manual_activate', 'hg.create.repository',
 
        'hg.fork.repository', 'repository.read', 'group.read'
 
    ]
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    user_log = relationship('UserLog')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
 

	
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 
    group_member = relationship('UserGroupMember', cascade='all')
 

	
 
    notifications = relationship('UserNotification', cascade='all')
 
    # notifications assigned to this user
 
    user_created_notifications = relationship('Notification', cascade='all')
 
    # comments created by this user
 
    user_comments = relationship('ChangesetComment', cascade='all')
 
    #extra emails for this user
 
    user_emails = relationship('UserEmailMap', cascade='all')
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 
    @property
 
    def firstname(self):
 
        # alias for future
 
        return self.name
 

	
 
    @property
 
    def emails(self):
 
        other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
 
        return [self.email] + [x.email for x in other]
 

	
 
    @property
 
    def ip_addresses(self):
 
        ret = UserIpMap.query().filter(UserIpMap.user == self).all()
 
        return [x.ip_addr for x in ret]
 

	
 
    @property
 
    def username_and_name(self):
 
        return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.firstname, self.lastname)
 
                if (self.firstname and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    def __unicode__(self):
 
        return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                     self.user_id, self.username)
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.email.ilike(email))
 
        else:
 
            q = cls.query().filter(cls.email == email)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_email_key_%s" % email))
 

	
 
@@ -482,298 +482,298 @@ class User(Base, BaseModel):
 
        return data
 

	
 
    def __json__(self):
 
        data = dict(
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 
        data.update(self.get_api_data())
 
        return data
 

	
 

	
 
class UserEmailMap(Base, BaseModel):
 
    __tablename__ = 'user_email_map'
 
    __table_args__ = (
 
        Index('uem_email_idx', 'email'),
 
        UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    user = relationship('User', lazy='joined')
 

	
 
    @validates('_email')
 
    def validate_email(self, key, email):
 
        # check if this email is not main one
 
        main_email = Session().query(User).filter(User.email == email).scalar()
 
        if main_email is not None:
 
            raise AttributeError('email %s is present is user table' % email)
 
        return email
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 

	
 
class UserIpMap(Base, BaseModel):
 
    __tablename__ = 'user_ip_map'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'ip_addr'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    user = relationship('User', lazy='joined')
 

	
 
    @classmethod
 
    def _get_ip_range(cls, ip_addr):
 
        from rhodecode.lib import ipaddr
 
        net = ipaddr.IPv4Network(ip_addr)
 
        return [str(net.network), str(net.broadcast)]
 

	
 
    def __json__(self):
 
        return dict(
 
          ip_addr=self.ip_addr,
 
          ip_range=self._get_ip_range(self.ip_addr)
 
        )
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
 
    repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository', cascade='')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
class UserGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    def get_api_data(self):
 
        users_group = self
 

	
 
        data = dict(
 
            users_group_id=users_group.users_group_id,
 
            group_name=users_group.users_group_name,
 
            active=users_group.users_group_active,
 
        )
 

	
 
        return data
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
class UserGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        Index('r_repo_name_idx', 'repo_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
    _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing',
 
                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
 
                             cascade='all')
 

	
 
    logs = relationship('UserLog')
 
    comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_org = relationship('PullRequest',
 
                    primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_other = relationship('PullRequest',
 
                    primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
 
                                   self.repo_name)
 

	
 
    @hybrid_property
 
    def locked(self):
 
        # always should return [user_id, timelocked]
 
        if self._locked:
 
            _lock_info = self._locked.split(':')
 
            return int(_lock_info[0]), _lock_info[1]
 
        return [None, None]
 

	
 
    @locked.setter
 
    def locked(self, val):
 
        if val and isinstance(val, (list, tuple)):
 
            self._locked = ':'.join(map(str, val))
 
        else:
 
            self._locked = None
 

	
 
    @hybrid_property
 
    def changeset_cache(self):
 
        from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
        dummy = EmptyChangeset().__json__()
 
        if not self._changeset_cache:
 
            return dummy
 
        try:
 
            return json.loads(self._changeset_cache)
 
        except TypeError:
 
            return dummy
 

	
 
    @changeset_cache.setter
 
    def changeset_cache(self, val):
 
        try:
 
            self._changeset_cache = json.dumps(val)
 
        except:
 
            log.error(traceback.format_exc())
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def normalize_repo_name(cls, repo_name):
 
        """
 
        Normalizes os specific repo_name to the format internally stored inside
 
        dabatabase using URL_SEP
 

	
 
        :param cls:
 
        :param repo_name:
 
        """
 
        return cls.url_sep().join(repo_name.split(os.sep))
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_full_path(cls, repo_full_path):
 
        repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
 
        repo_name = cls.normalize_repo_name(repo_name)
 
        return cls.get_by_repo_name(repo_name.strip(URL_SEP))
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
        q = Session().query(RhodeCodeUi)\
 
            .filter(RhodeCodeUi.ui_key == cls.url_sep())
 
@@ -1046,193 +1046,193 @@ class Repository(Base, BaseModel):
 
            pr_id = pr_repo = None
 
            if stat.pull_request:
 
                pr_id = stat.pull_request.pull_request_id
 
                pr_repo = stat.pull_request.other_repo.repo_name
 
            grouped[stat.revision] = [str(stat.status), stat.status_lbl,
 
                                      pr_id, pr_repo]
 
        return grouped
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(repo_name=self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        import rhodecode
 
        full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, cache_map=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 

	
 
        if cache_map:
 
            # get using prefilled cache_map
 
            invalidate_repo = cache_map[self.repo_name]
 
            if invalidate_repo:
 
                invalidate_repo = (None if invalidate_repo.cache_active
 
                                   else invalidate_repo)
 
        else:
 
            # get from invalidate
 
            invalidate_repo = self.invalidate
 

	
 
        if invalidate_repo is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(invalidate_repo.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository' % alias)
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    __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(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(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
 

	
 
    parent_group = relationship('RepoGroup', remote_side=group_id)
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @classmethod
 
    def groups_choices(cls, check_perms=False):
 
        from webhelpers.html import literal as _literal
 
        from rhodecode.model.scm import ScmModel
 
        groups = cls.query().all()
 
        if check_perms:
 
            #filter group user have access to, it's done
 
            #magically inside ScmModel based on current user
 
            groups = ScmModel().get_repos_groups(groups)
 
        repo_groups = [('', '')]
 
        sep = ' &raquo; '
 
        _name = lambda k: _literal(sep.join(k))
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in groups])
 

	
 
        repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
 
        return repo_groups
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_group_%s" % _hash_key(group_name)
 
                            )
 
            )
 
        return gr.scalar()
 

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return RepoGroup.query().filter(RepoGroup.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(RepoGroup.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query()\
 
                .filter(Repository.group == self)\
 
                .order_by(Repository.repo_name)
 

	
 
@@ -1310,268 +1310,268 @@ class Permission(Base, BaseModel):
 
    ]
 

	
 
    # defines which permissions are more important higher the more important
 
    PERM_WEIGHTS = {
 
        'repository.none': 0,
 
        'repository.read': 1,
 
        'repository.write': 3,
 
        'repository.admin': 4,
 

	
 
        'group.none': 0,
 
        'group.read': 1,
 
        'group.write': 3,
 
        'group.admin': 4,
 

	
 
        'hg.fork.none': 0,
 
        'hg.fork.repository': 1,
 
        'hg.create.none': 0,
 
        'hg.create.repository':1
 
    }
 

	
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__, self.permission_id, self.permission_name
 
        )
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session().query(UserRepoToPerm, Repository, cls)\
 
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    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')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_to_perm_id = Column("user_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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
class UserGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_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)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
class UserGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    group_to_perm_id = Column("group_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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
class UserGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (
 
         UniqueConstraint('repository_id'),
 
         {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
          'mysql_charset': 'utf8'}
 
    )
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'follows_repository_id'),
 
        UniqueConstraint('user_id', 'follows_user_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    user_following_id = Column("user_following_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)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (
 
        UniqueConstraint('cache_key'),
 
        Index('key_idx', 'cache_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.cache_id, self.cache_key)
 

	
 
    @property
 
    def prefix(self):
 
        _split = self.cache_key.split(self.cache_args, 1)
 
        if _split and len(_split) == 2:
 
            return _split[0]
 
        return ''
 

	
 
    @classmethod
 
    def clear_cache(cls):
 
        cls.query().delete()
 

	
 
    @classmethod
 
    def _get_key(cls, key):
 
        """
 
        Wrapper for generating a key, together with a prefix
 

	
 
        :param key:
 
        """
 
        import rhodecode
 
        prefix = ''
 
        org_key = key
 
        iid = rhodecode.CONFIG.get('instance_id')
 
        if iid:
 
            prefix = iid
 

	
 
        return "%s%s" % (prefix, key), prefix, org_key
 

	
 
    @classmethod
rhodecode/lib/dbmigrate/versions/003_version_1_2_0.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 

	
 
    #==========================================================================
 
    # Add table `groups``
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import Group as Group
 
    Group().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserRepoGroupToPerm
 
    UserRepoGroupToPerm().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `users_groups`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroup
 
    UsersGroup().__table__.create()
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroup
 
    UserGroup().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `users_groups_members`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroupMember
 
    UsersGroupMember().__table__.create()
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupMember
 
    UserGroupMember().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `users_group_repo_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroupRepoToPerm
 
    UsersGroupRepoToPerm().__table__.create()
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupRepoToPerm
 
    UserGroupRepoToPerm().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `users_group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UsersGroupToPerm
 
    UsersGroupToPerm().__table__.create()
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserGroupToPerm
 
    UserGroupToPerm().__table__.create()
 

	
 
    #==========================================================================
 
    # Upgrade of `users` table
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import User
 

	
 
    #add column
 
    ldap_dn = Column("ldap_dn", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ldap_dn.create(User().__table__)
 

	
 
    api_key = Column("api_key", String(length=255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key.create(User().__table__)
 

	
 
    #remove old column
 
    is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
 
    is_ldap.drop(User().__table__)
 

	
 
    #==========================================================================
 
    # Upgrade of `repositories` table
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import Repository
 

	
 
    #ADD clone_uri column#
 

	
 
    clone_uri = Column("clone_uri", String(length=255, convert_unicode=False,
 
                                           assert_unicode=None),
 
                        nullable=True, unique=False, default=None)
 

	
 
    clone_uri.create(Repository().__table__)
 

	
 
    #ADD downloads column#
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads.create(Repository().__table__)
 

	
 
    #ADD column created_on
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True,
 
                        unique=None, default=datetime.datetime.now)
 
    created_on.create(Repository().__table__)
 

	
 
    #ADD group_id column#
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'),
 
                  nullable=True, unique=False, default=None)
 

	
 
    group_id.create(Repository().__table__)
 

	
 
    #==========================================================================
 
    # Upgrade of `user_followings` table
 
    #==========================================================================
 

	
 
    from rhodecode.lib.dbmigrate.schema.db_1_2_0 import UserFollowing
 

	
 
    follows_from = Column('follows_from', DateTime(timezone=False),
 
                          nullable=True, unique=None,
 
                          default=datetime.datetime.now)
 
    follows_from.create(UserFollowing().__table__)
 

	
 
    return
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
rhodecode/lib/dbmigrate/versions/004_version_1_3_0.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """ Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 
    #==========================================================================
 
    # Add table `users_group_repo_group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroupRepoGroupToPerm
 
    UsersGroupRepoGroupToPerm().__table__.create()
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroupRepoGroupToPerm
 
    UserGroupRepoGroupToPerm().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `changeset_comments`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import  ChangesetComment
 
    ChangesetComment().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `notifications`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import  Notification
 
    Notification().__table__.create()
 

	
 
    #==========================================================================
 
    # Add table `user_to_notification`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import  UserNotification
 
    UserNotification().__table__.create()
 

	
 
    #==========================================================================
 
    # Add unique to table `users_group_to_perm`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroupToPerm
 
    tbl = UsersGroupToPerm().__table__
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroupToPerm
 
    tbl = UserGroupToPerm().__table__
 
    cons = UniqueConstraint('users_group_id', 'permission_id', table=tbl)
 
    cons.create()
 

	
 
    #==========================================================================
 
    # Fix unique constrain on table `user_logs`
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserLog
 
    tbl = UserLog().__table__
 
    col = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'),
 
                 nullable=False, unique=None, default=None)
 
    col.alter(nullable=True, table=tbl)
 

	
 
    #==========================================================================
 
    # Rename table `group_to_perm` to `user_repo_group_to_perm`
 
    #==========================================================================
 
    tbl = Table('group_to_perm', MetaData(bind=migrate_engine), autoload=True,
 
                    autoload_with=migrate_engine)
 
    tbl.rename('user_repo_group_to_perm')
 

	
 
    return
 

	
 

	
 
def downgrade(migrate_engine):
 
    meta = MetaData()
 
    meta.bind = migrate_engine
rhodecode/lib/dbmigrate/versions/006_version_1_4_0.py
Show inline comments
 
import logging
 
import datetime
 

	
 
from sqlalchemy import *
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import relation, backref, class_mapper
 
from sqlalchemy.orm.session import Session
 
from sqlalchemy.ext.declarative import declarative_base
 

	
 
from rhodecode.lib.dbmigrate.migrate import *
 
from rhodecode.lib.dbmigrate.migrate.changeset import *
 

	
 
from rhodecode.model.meta import Base
 
from rhodecode.model import meta
 
from rhodecode.lib.dbmigrate.versions import _reset_base
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
def upgrade(migrate_engine):
 
    """
 
    Upgrade operations go here.
 
    Don't create your own engine; bind migrate_engine to your metadata
 
    """
 

	
 
    #==========================================================================
 
    # USEREMAILMAP
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_4_0 import UserEmailMap
 
    tbl = UserEmailMap.__table__
 
    tbl.create()
 
    #==========================================================================
 
    # PULL REQUEST
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_4_0 import PullRequest
 
    tbl = PullRequest.__table__
 
    tbl.create()
 

	
 
    #==========================================================================
 
    # PULL REQUEST REVIEWERS
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_4_0 import PullRequestReviewers
 
    tbl = PullRequestReviewers.__table__
 
    tbl.create()
 

	
 
    #==========================================================================
 
    # CHANGESET STATUS
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_4_0 import ChangesetStatus
 
    tbl = ChangesetStatus.__table__
 
    tbl.create()
 

	
 
    _reset_base(migrate_engine)
 

	
 
    #==========================================================================
 
    # USERS TABLE
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import User
 
    tbl = User.__table__
 

	
 
    # change column name -> firstname
 
    col = User.__table__.columns.name
 
    col.alter(index=Index('u_username_idx', 'username'))
 
    col.alter(index=Index('u_email_idx', 'email'))
 
    col.alter(name="firstname", table=tbl)
 

	
 
    # add inherit_default_permission column
 
    inherit_default_permissions = Column("inherit_default_permissions",
 
                                         Boolean(), nullable=True, unique=None,
 
                                         default=True)
 
    inherit_default_permissions.create(table=tbl)
 
    inherit_default_permissions.alter(nullable=False, default=True, table=tbl)
 

	
 
    #==========================================================================
 
    # USERS GROUP TABLE
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UsersGroup
 
    tbl = UsersGroup.__table__
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import UserGroup
 
    tbl = UserGroup.__table__
 
    # add inherit_default_permission column
 
    gr_inherit_default_permissions = Column(
 
                                    "users_group_inherit_default_permissions",
 
                                    Boolean(), nullable=True, unique=None,
 
                                    default=True)
 
    gr_inherit_default_permissions.create(table=tbl)
 
    gr_inherit_default_permissions.alter(nullable=False, default=True, table=tbl)
 

	
 
    #==========================================================================
 
    # REPOSITORIES
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import Repository
 
    tbl = Repository.__table__
 

	
 
    # add enable locking column
 
    enable_locking = Column("enable_locking", Boolean(), nullable=True,
 
                            unique=None, default=False)
 
    enable_locking.create(table=tbl)
 
    enable_locking.alter(nullable=False, default=False, table=tbl)
 

	
 
    # add locked column
 
    _locked = Column("locked", String(255), nullable=True, unique=False,
 
                     default=None)
 
    _locked.create(table=tbl)
 

	
 
    #add langing revision column
 
    landing_rev = Column("landing_revision", String(255), nullable=True,
 
                         unique=False, default='tip')
 
    landing_rev.create(table=tbl)
 
    landing_rev.alter(nullable=False, default='tip', table=tbl)
 

	
 
    #==========================================================================
 
    # GROUPS
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import RepoGroup
 
    tbl = RepoGroup.__table__
 

	
 
    # add enable locking column
 
    enable_locking = Column("enable_locking", Boolean(), nullable=True,
 
                            unique=None, default=False)
 
    enable_locking.create(table=tbl)
 
    enable_locking.alter(nullable=False, default=False)
 

	
 
    #==========================================================================
 
    # CACHE INVALIDATION
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import CacheInvalidation
 
    tbl = CacheInvalidation.__table__
 

	
 
    # add INDEX for cache keys
 
    col = CacheInvalidation.__table__.columns.cache_key
 
    col.alter(index=Index('key_idx', 'cache_key'))
 

	
 
    #==========================================================================
 
    # NOTIFICATION
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import Notification
 
    tbl = Notification.__table__
 

	
 
    # add index for notification type
 
    col = Notification.__table__.columns.type
 
    col.alter(index=Index('notification_type_idx', 'type'),)
 

	
 
    #==========================================================================
 
    # CHANGESET_COMMENTS
 
    #==========================================================================
 
    from rhodecode.lib.dbmigrate.schema.db_1_3_0 import ChangesetComment
 

	
 
    tbl = ChangesetComment.__table__
 
    col = ChangesetComment.__table__.columns.revision
 

	
 
    # add index for revisions
 
    col.alter(index=Index('cc_revision_idx', 'revision'),)
 

	
 
    # add hl_lines column
 
    hl_lines = Column('hl_lines', Unicode(512), nullable=True)
 
    hl_lines.create(table=tbl)
 

	
 
    # add created_on column
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True,
 
                        default=datetime.datetime.now)
 
    created_on.create(table=tbl)
 
    created_on.alter(nullable=False, default=datetime.datetime.now)
 

	
 
    modified_at = Column('modified_at', DateTime(timezone=False), nullable=False,
 
                         default=datetime.datetime.now)
 
    modified_at.alter(type=DateTime(timezone=False), table=tbl)
 

	
 
    # add FK to pull_request
 
    pull_request_id = Column("pull_request_id", Integer(),
 
                             ForeignKey('pull_requests.pull_request_id'),
 
                             nullable=True)
 
    pull_request_id.create(table=tbl)
 
    _reset_base(migrate_engine)
 

	
 

	
rhodecode/lib/exceptions.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.lib.exceptions
 
    ~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    Set of custom exceptions used in RhodeCode
 

	
 
    :created_on: Nov 17, 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/>.
 

	
 
from webob.exc import HTTPClientError
 

	
 

	
 
class LdapUsernameError(Exception):
 
    pass
 

	
 

	
 
class LdapPasswordError(Exception):
 
    pass
 

	
 

	
 
class LdapConnectionError(Exception):
 
    pass
 

	
 

	
 
class LdapImportError(Exception):
 
    pass
 

	
 

	
 
class DefaultUserException(Exception):
 
    pass
 

	
 

	
 
class UserOwnsReposException(Exception):
 
    pass
 

	
 

	
 
class UsersGroupsAssignedException(Exception):
 
class UserGroupsAssignedException(Exception):
 
    pass
 

	
 

	
 
class StatusChangeOnClosedPullRequestError(Exception):
 
    pass
 

	
 

	
 
class HTTPLockedRC(HTTPClientError):
 
    """
 
    Special Exception For locked Repos in RhodeCode
 
    """
 
    code = 423
 
    title = explanation = 'Repository Locked'
 

	
 
    def __init__(self, reponame, username, *args, **kwargs):
 
        self.title = self.explanation = ('Repository `%s` locked by '
 
                                         'user `%s`' % (reponame, username))
 
        super(HTTPLockedRC, self).__init__(*args, **kwargs)
rhodecode/model/db.py
Show inline comments
 
@@ -248,193 +248,193 @@ class RhodeCodeUi(Base, BaseModel):
 
    __table_args__ = (
 
        UniqueConstraint('ui_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    HOOK_UPDATE = 'changegroup.update'
 
    HOOK_REPO_SIZE = 'changegroup.repo_size'
 
    HOOK_PUSH = 'changegroup.push_logger'
 
    HOOK_PRE_PUSH = 'prechangegroup.pre_push'
 
    HOOK_PULL = 'outgoing.pull_logger'
 
    HOOK_PRE_PULL = 'preoutgoing.pre_pull'
 

	
 
    ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.ui_key == key).scalar()
 

	
 
    @classmethod
 
    def get_builtin_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                     cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                     cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        return q.all()
 

	
 
    @classmethod
 
    def get_custom_hooks(cls):
 
        q = cls.query()
 
        q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
 
                                      cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
 
                                      cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
 
        q = q.filter(cls.ui_section == 'hooks')
 
        return q.all()
 

	
 
    @classmethod
 
    def get_repos_location(cls):
 
        return cls.get_by_key('/').ui_value
 

	
 
    @classmethod
 
    def create_or_update_hook(cls, key, val):
 
        new_ui = cls.get_by_key(key) or cls()
 
        new_ui.ui_section = 'hooks'
 
        new_ui.ui_active = True
 
        new_ui.ui_key = key
 
        new_ui.ui_value = val
 

	
 
        Session().add(new_ui)
 

	
 
    def __repr__(self):
 
        return '<DB:%s[%s:%s]>' % (self.__class__.__name__, self.ui_key,
 
                                   self.ui_value)
 

	
 

	
 
class User(Base, BaseModel):
 
    __tablename__ = 'users'
 
    __table_args__ = (
 
        UniqueConstraint('username'), UniqueConstraint('email'),
 
        Index('u_username_idx', 'username'),
 
        Index('u_email_idx', 'email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    DEFAULT_USER = 'default'
 
    DEFAULT_PERMISSIONS = [
 
        'hg.register.manual_activate', 'hg.create.repository',
 
        'hg.fork.repository', 'repository.read', 'group.read'
 
    ]
 
    user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    user_log = relationship('UserLog')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
 
    followings = relationship('UserFollowing', primaryjoin='UserFollowing.user_id==User.user_id', cascade='all')
 

	
 
    repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
 

	
 
    group_member = relationship('UsersGroupMember', cascade='all')
 
    group_member = relationship('UserGroupMember', cascade='all')
 

	
 
    notifications = relationship('UserNotification', cascade='all')
 
    # notifications assigned to this user
 
    user_created_notifications = relationship('Notification', cascade='all')
 
    # comments created by this user
 
    user_comments = relationship('ChangesetComment', cascade='all')
 
    #extra emails for this user
 
    user_emails = relationship('UserEmailMap', cascade='all')
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 
    @property
 
    def firstname(self):
 
        # alias for future
 
        return self.name
 

	
 
    @property
 
    def emails(self):
 
        other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
 
        return [self.email] + [x.email for x in other]
 

	
 
    @property
 
    def ip_addresses(self):
 
        ret = UserIpMap.query().filter(UserIpMap.user == self).all()
 
        return [x.ip_addr for x in ret]
 

	
 
    @property
 
    def username_and_name(self):
 
        return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.firstname, self.lastname)
 
                if (self.firstname and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
 

	
 
    @property
 
    def short_contact(self):
 
        return '%s %s' % (self.firstname, self.lastname)
 

	
 
    @property
 
    def is_admin(self):
 
        return self.admin
 

	
 
    @property
 
    def AuthUser(self):
 
        """
 
        Returns instance of AuthUser for this user
 
        """
 
        from rhodecode.lib.auth import AuthUser
 
        return AuthUser(user_id=self.user_id, api_key=self.api_key,
 
                        username=self.username)
 

	
 
    def __unicode__(self):
 
        return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
 
                                     self.user_id, self.username)
 

	
 
    @classmethod
 
    def get_by_username(cls, username, case_insensitive=False, cache=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.username.ilike(username))
 
        else:
 
            q = cls.query().filter(cls.username == username)
 

	
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(username)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_api_key(cls, api_key, cache=False):
 
        q = cls.query().filter(cls.api_key == api_key)
 

	
 
        if cache:
 
            q = q.options(FromCache("sql_cache_short",
 
                                    "get_api_key_%s" % api_key))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_email(cls, email, case_insensitive=False, cache=False):
 
@@ -511,336 +511,336 @@ class User(Base, BaseModel):
 
        return data
 

	
 
    def __json__(self):
 
        data = dict(
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 
        data.update(self.get_api_data())
 
        return data
 

	
 

	
 
class UserEmailMap(Base, BaseModel):
 
    __tablename__ = 'user_email_map'
 
    __table_args__ = (
 
        Index('uem_email_idx', 'email'),
 
        UniqueConstraint('email'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    user = relationship('User', lazy='joined')
 

	
 
    @validates('_email')
 
    def validate_email(self, key, email):
 
        # check if this email is not main one
 
        main_email = Session().query(User).filter(User.email == email).scalar()
 
        if main_email is not None:
 
            raise AttributeError('email %s is present is user table' % email)
 
        return email
 

	
 
    @hybrid_property
 
    def email(self):
 
        return self._email
 

	
 
    @email.setter
 
    def email(self, val):
 
        self._email = val.lower() if val else None
 

	
 

	
 
class UserIpMap(Base, BaseModel):
 
    __tablename__ = 'user_ip_map'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'ip_addr'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    __mapper_args__ = {}
 

	
 
    ip_id = Column("ip_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    ip_addr = Column("ip_addr", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=True)
 
    user = relationship('User', lazy='joined')
 

	
 
    @classmethod
 
    def _get_ip_range(cls, ip_addr):
 
        from rhodecode.lib import ipaddr
 
        net = ipaddr.IPNetwork(address=ip_addr)
 
        return [str(net.network), str(net.broadcast)]
 

	
 
    def __json__(self):
 
        return dict(
 
          ip_addr=self.ip_addr,
 
          ip_range=self._get_ip_range(self.ip_addr)
 
        )
 

	
 

	
 
class UserLog(Base, BaseModel):
 
    __tablename__ = 'user_logs'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
 
    repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
 

	
 
    @property
 
    def action_as_day(self):
 
        return datetime.date(*self.action_date.timetuple()[:3])
 

	
 
    user = relationship('User')
 
    repository = relationship('Repository', cascade='')
 

	
 

	
 
class UsersGroup(Base, BaseModel):
 
class UserGroup(Base, BaseModel):
 
    __tablename__ = 'users_groups'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
 
    inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
 

	
 
    members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    members = relationship('UserGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
 
    users_group_to_perm = relationship('UserGroupToPerm', cascade='all')
 
    users_group_repo_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 

	
 
    def __unicode__(self):
 
        return u'<userGroup(%s)>' % (self.users_group_name)
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False,
 
                          case_insensitive=False):
 
        if case_insensitive:
 
            q = cls.query().filter(cls.users_group_name.ilike(group_name))
 
        else:
 
            q = cls.query().filter(cls.users_group_name == group_name)
 
        if cache:
 
            q = q.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_user_%s" % _hash_key(group_name)
 
                          )
 
            )
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get(cls, users_group_id, cache=False):
 
        users_group = cls.query()
 
        if cache:
 
            users_group = users_group.options(FromCache("sql_cache_short",
 
                                    "get_users_group_%s" % users_group_id))
 
        return users_group.get(users_group_id)
 

	
 
    def get_api_data(self):
 
        users_group = self
 

	
 
        data = dict(
 
            users_group_id=users_group.users_group_id,
 
            group_name=users_group.users_group_name,
 
            active=users_group.users_group_active,
 
        )
 

	
 
        return data
 

	
 

	
 
class UsersGroupMember(Base, BaseModel):
 
class UserGroupMember(Base, BaseModel):
 
    __tablename__ = 'users_groups_members'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User', lazy='joined')
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 

	
 
    def __init__(self, gr_id='', u_id=''):
 
        self.users_group_id = gr_id
 
        self.user_id = u_id
 

	
 

	
 
class RepositoryField(Base, BaseModel):
 
    __tablename__ = 'repositories_fields'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'field_key'),  # no-multi field
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    PREFIX = 'ex_'  # prefix used in form to not conflict with already existing fields
 

	
 
    repo_field_id = Column("repo_field_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
 
    field_key = Column("field_key", String(250, convert_unicode=False, assert_unicode=None))
 
    field_label = Column("field_label", String(1024, convert_unicode=False, assert_unicode=None), nullable=False)
 
    field_value = Column("field_value", String(10000, convert_unicode=False, assert_unicode=None), nullable=False)
 
    field_desc = Column("field_desc", String(1024, convert_unicode=False, assert_unicode=None), nullable=False)
 
    field_type = Column("field_type", String(256), nullable=False, unique=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 

	
 
    repository = relationship('Repository')
 

	
 
    @property
 
    def field_key_prefixed(self):
 
        return 'ex_%s' % self.field_key
 

	
 
    @classmethod
 
    def un_prefix_key(cls, key):
 
        if key.startswith(cls.PREFIX):
 
            return key[len(cls.PREFIX):]
 
        return key
 

	
 
    @classmethod
 
    def get_by_key_name(cls, key, repo):
 
        row = cls.query()\
 
                .filter(cls.repository == repo)\
 
                .filter(cls.field_key == key).scalar()
 
        return row
 

	
 

	
 
class Repository(Base, BaseModel):
 
    __tablename__ = 'repositories'
 
    __table_args__ = (
 
        UniqueConstraint('repo_name'),
 
        Index('r_repo_name_idx', 'repo_name'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 

	
 
    repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
 
    clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
 
    private = Column("private", Boolean(), nullable=True, unique=None, default=None)
 
    enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
 
    enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
 
    description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 
    landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
    _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
 
    _changeset_cache = Column("changeset_cache", LargeBinary(), nullable=True) #JSON data
 

	
 
    fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
 

	
 
    user = relationship('User')
 
    fork = relationship('Repository', remote_side=repo_id)
 
    group = relationship('RepoGroup')
 
    repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoToPerm', cascade='all')
 
    stats = relationship('Statistics', cascade='all', uselist=False)
 

	
 
    followers = relationship('UserFollowing',
 
                             primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
 
                             cascade='all')
 
    extra_fields = relationship('RepositoryField',
 
                                cascade="all, delete, delete-orphan")
 

	
 
    logs = relationship('UserLog')
 
    comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_org = relationship('PullRequest',
 
                    primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    pull_requests_other = relationship('PullRequest',
 
                    primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
 
                    cascade="all, delete, delete-orphan")
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
 
                                   self.repo_name)
 

	
 
    @hybrid_property
 
    def locked(self):
 
        # always should return [user_id, timelocked]
 
        if self._locked:
 
            _lock_info = self._locked.split(':')
 
            return int(_lock_info[0]), _lock_info[1]
 
        return [None, None]
 

	
 
    @locked.setter
 
    def locked(self, val):
 
        if val and isinstance(val, (list, tuple)):
 
            self._locked = ':'.join(map(str, val))
 
        else:
 
            self._locked = None
 

	
 
    @hybrid_property
 
    def changeset_cache(self):
 
        from rhodecode.lib.vcs.backends.base import EmptyChangeset
 
        dummy = EmptyChangeset().__json__()
 
        if not self._changeset_cache:
 
            return dummy
 
        try:
 
            return json.loads(self._changeset_cache)
 
        except TypeError:
 
            return dummy
 

	
 
    @changeset_cache.setter
 
    def changeset_cache(self, val):
 
        try:
 
            self._changeset_cache = json.dumps(val)
 
        except:
 
            log.error(traceback.format_exc())
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def normalize_repo_name(cls, repo_name):
 
        """
 
        Normalizes os specific repo_name to the format internally stored inside
 
        dabatabase using URL_SEP
 

	
 
        :param cls:
 
        :param repo_name:
 
        """
 
        return cls.url_sep().join(repo_name.split(os.sep))
 

	
 
    @classmethod
 
    def get_by_repo_name(cls, repo_name):
 
        q = Session().query(cls).filter(cls.repo_name == repo_name)
 
        q = q.options(joinedload(Repository.fork))\
 
                .options(joinedload(Repository.user))\
 
                .options(joinedload(Repository.group))
 
        return q.scalar()
 

	
 
    @classmethod
 
    def get_by_full_path(cls, repo_full_path):
 
        repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
 
        repo_name = cls.normalize_repo_name(repo_name)
 
        return cls.get_by_repo_name(repo_name.strip(URL_SEP))
 

	
 
    @classmethod
 
    def get_repo_forks(cls, repo_id):
 
        return cls.query().filter(Repository.fork_id == repo_id)
 

	
 
    @classmethod
 
    def base_path(cls):
 
        """
 
        Returns base path when all repos are stored
 

	
 
        :param cls:
 
        """
 
@@ -1134,193 +1134,193 @@ class Repository(Base, BaseModel):
 
        from rhodecode.lib import helpers as h
 
        log.debug('calculating repository size...')
 
        return h.format_byte_size(self.scm_instance.size)
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    @property
 
    def invalidate(self):
 
        return CacheInvalidation.invalidate(self.repo_name)
 

	
 
    def set_invalidate(self):
 
        """
 
        set a cache for invalidation for this instance
 
        """
 
        CacheInvalidation.set_invalidate(repo_name=self.repo_name)
 

	
 
    @LazyProperty
 
    def scm_instance_no_cache(self):
 
        return self.__get_instance()
 

	
 
    @LazyProperty
 
    def scm_instance(self):
 
        import rhodecode
 
        full_cache = str2bool(rhodecode.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, cache_map=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 
        log.debug('Getting cached instance of repo')
 

	
 
        if cache_map:
 
            # get using prefilled cache_map
 
            invalidate_repo = cache_map[self.repo_name]
 
            if invalidate_repo:
 
                invalidate_repo = (None if invalidate_repo.cache_active
 
                                   else invalidate_repo)
 
        else:
 
            # get from invalidate
 
            invalidate_repo = self.invalidate
 

	
 
        if invalidate_repo is not None:
 
            region_invalidate(_c, None, rn)
 
            # update our cache
 
            CacheInvalidation.set_valid(invalidate_repo.cache_key)
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository' % alias)
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    __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(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(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 

	
 
    repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
 
    users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
 
    users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
 

	
 
    parent_group = relationship('RepoGroup', remote_side=group_id)
 

	
 
    def __init__(self, group_name='', parent_group=None):
 
        self.group_name = group_name
 
        self.parent_group = parent_group
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
 
                                  self.group_name)
 

	
 
    @classmethod
 
    def groups_choices(cls, groups=None, show_empty_group=True):
 
        from webhelpers.html import literal as _literal
 
        if not groups:
 
            groups = cls.query().all()
 

	
 
        repo_groups = []
 
        if show_empty_group:
 
            repo_groups = [('-1', '-- no parent --')]
 
        sep = ' &raquo; '
 
        _name = lambda k: _literal(sep.join(k))
 

	
 
        repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
 
                              for x in groups])
 

	
 
        repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
 
        return repo_groups
 

	
 
    @classmethod
 
    def url_sep(cls):
 
        return URL_SEP
 

	
 
    @classmethod
 
    def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
 
        if case_insensitive:
 
            gr = cls.query()\
 
                .filter(cls.group_name.ilike(group_name))
 
        else:
 
            gr = cls.query()\
 
                .filter(cls.group_name == group_name)
 
        if cache:
 
            gr = gr.options(FromCache(
 
                            "sql_cache_short",
 
                            "get_group_%s" % _hash_key(group_name)
 
                            )
 
            )
 
        return gr.scalar()
 

	
 
    @property
 
    def parents(self):
 
        parents_recursion_limit = 5
 
        groups = []
 
        if self.parent_group is None:
 
            return groups
 
        cur_gr = self.parent_group
 
        groups.insert(0, cur_gr)
 
        cnt = 0
 
        while 1:
 
            cnt += 1
 
            gr = getattr(cur_gr, 'parent_group', None)
 
            cur_gr = cur_gr.parent_group
 
            if gr is None:
 
                break
 
            if cnt == parents_recursion_limit:
 
                # this will prevent accidental infinit loops
 
                log.error('group nested more than %s' %
 
                          parents_recursion_limit)
 
                break
 

	
 
            groups.insert(0, gr)
 
        return groups
 

	
 
    @property
 
    def children(self):
 
        return RepoGroup.query().filter(RepoGroup.parent_group == self)
 

	
 
    @property
 
    def name(self):
 
        return self.group_name.split(RepoGroup.url_sep())[-1]
 

	
 
    @property
 
    def full_path(self):
 
        return self.group_name
 

	
 
    @property
 
    def full_path_splitted(self):
 
        return self.group_name.split(RepoGroup.url_sep())
 

	
 
    @property
 
    def repositories(self):
 
        return Repository.query()\
 
                .filter(Repository.group == self)\
 
                .order_by(Repository.repo_name)
 

	
 
    @property
 
@@ -1397,268 +1397,268 @@ class Permission(Base, BaseModel):
 
    ]
 

	
 
    # defines which permissions are more important higher the more important
 
    PERM_WEIGHTS = {
 
        'repository.none': 0,
 
        'repository.read': 1,
 
        'repository.write': 3,
 
        'repository.admin': 4,
 

	
 
        'group.none': 0,
 
        'group.read': 1,
 
        'group.write': 3,
 
        'group.admin': 4,
 

	
 
        'hg.fork.none': 0,
 
        'hg.fork.repository': 1,
 
        'hg.create.none': 0,
 
        'hg.create.repository':1
 
    }
 

	
 
    permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__, self.permission_id, self.permission_name
 
        )
 

	
 
    @classmethod
 
    def get_by_key(cls, key):
 
        return cls.query().filter(cls.permission_name == key).scalar()
 

	
 
    @classmethod
 
    def get_default_perms(cls, default_user_id):
 
        q = Session().query(UserRepoToPerm, Repository, cls)\
 
         .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
 
         .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 
    @classmethod
 
    def get_default_group_perms(cls, default_user_id):
 
        q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == default_user_id)
 

	
 
        return q.all()
 

	
 

	
 
class UserRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'repository_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    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')
 
    repository = relationship('Repository')
 
    permission = relationship('Permission')
 

	
 
    @classmethod
 
    def create(cls, user, repository, permission):
 
        n = cls()
 
        n.user = user
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<user:%s => %s >' % (self.user, self.repository)
 

	
 

	
 
class UserToPerm(Base, BaseModel):
 
    __tablename__ = 'user_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    user_to_perm_id = Column("user_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)
 

	
 
    user = relationship('User')
 
    permission = relationship('Permission', lazy='joined')
 

	
 

	
 
class UsersGroupRepoToPerm(Base, BaseModel):
 
class UserGroupRepoToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_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)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    repository = relationship('Repository')
 

	
 
    @classmethod
 
    def create(cls, users_group, repository, permission):
 
        n = cls()
 
        n.users_group = users_group
 
        n.repository = repository
 
        n.permission = permission
 
        Session().add(n)
 
        return n
 

	
 
    def __unicode__(self):
 
        return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
 

	
 

	
 
class UsersGroupToPerm(Base, BaseModel):
 
class UserGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'permission_id',),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 
    users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UserRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'user_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'group_id', 'permission_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    group_to_perm_id = Column("group_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)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    user = relationship('User')
 
    group = relationship('RepoGroup')
 
    permission = relationship('Permission')
 

	
 

	
 
class UsersGroupRepoGroupToPerm(Base, BaseModel):
 
class UserGroupRepoGroupToPerm(Base, BaseModel):
 
    __tablename__ = 'users_group_repo_group_to_perm'
 
    __table_args__ = (
 
        UniqueConstraint('users_group_id', 'group_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
 
    group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
 
    permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
 

	
 
    users_group = relationship('UsersGroup')
 
    users_group = relationship('UserGroup')
 
    permission = relationship('Permission')
 
    group = relationship('RepoGroup')
 

	
 

	
 
class Statistics(Base, BaseModel):
 
    __tablename__ = 'statistics'
 
    __table_args__ = (
 
         UniqueConstraint('repository_id'),
 
         {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
          'mysql_charset': 'utf8'}
 
    )
 
    stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
 
    stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
 
    commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
 
    commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
 
    languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
 

	
 
    repository = relationship('Repository', single_parent=True)
 

	
 

	
 
class UserFollowing(Base, BaseModel):
 
    __tablename__ = 'user_followings'
 
    __table_args__ = (
 
        UniqueConstraint('user_id', 'follows_repository_id'),
 
        UniqueConstraint('user_id', 'follows_user_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'}
 
    )
 

	
 
    user_following_id = Column("user_following_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)
 
    follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
 
    follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
 
    follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
 

	
 
    user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
 

	
 
    follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
 
    follows_repository = relationship('Repository', order_by='Repository.repo_name')
 

	
 
    @classmethod
 
    def get_repo_followers(cls, repo_id):
 
        return cls.query().filter(cls.follows_repo_id == repo_id)
 

	
 

	
 
class CacheInvalidation(Base, BaseModel):
 
    __tablename__ = 'cache_invalidation'
 
    __table_args__ = (
 
        UniqueConstraint('cache_key'),
 
        Index('key_idx', 'cache_key'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8'},
 
    )
 
    cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
 

	
 
    def __init__(self, cache_key, cache_args=''):
 
        self.cache_key = cache_key
 
        self.cache_args = cache_args
 
        self.cache_active = False
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (self.__class__.__name__,
 
                                  self.cache_id, self.cache_key)
 

	
 
    @property
 
    def prefix(self):
 
        _split = self.cache_key.split(self.cache_args, 1)
 
        if _split and len(_split) == 2:
 
            return _split[0]
 
        return ''
 

	
 
    @classmethod
 
    def clear_cache(cls):
 
        cls.query().delete()
 

	
 
    @classmethod
 
    def _get_key(cls, key):
 
        """
 
        Wrapper for generating a key, together with a prefix
 

	
 
        :param key:
 
        """
 
        import rhodecode
 
        prefix = ''
 
        org_key = key
 
        iid = rhodecode.CONFIG.get('instance_id')
 
        if iid:
 
            prefix = iid
 

	
 
        return "%s%s" % (prefix, key), prefix, org_key
 

	
 
    @classmethod
rhodecode/model/forms.py
Show inline comments
 
""" this is forms validation classes
 
http://formencode.org/module-formencode.validators.html
 
for list off all availible validators
 

	
 
we can create our own validators
 

	
 
The table below outlines the options which can be used in a schema in addition to the validators themselves
 
pre_validators          []     These validators will be applied before the schema
 
chained_validators      []     These validators will be applied after the schema
 
allow_extra_fields      False     If True, then it is not an error when keys that aren't associated with a validator are present
 
filter_extra_fields     False     If True, then keys that aren't associated with a validator are removed
 
if_key_missing          NoDefault If this is given, then any keys that aren't available but are expected will be replaced with this value (and then validated). This does not override a present .if_missing attribute on validators. NoDefault is a special FormEncode class to mean that no default values has been specified and therefore missing keys shouldn't take a default value.
 
ignore_key_missing      False     If True, then missing keys will be missing in the result, if the validator doesn't have .if_missing on it already
 

	
 

	
 
<name> = formencode.validators.<name of validator>
 
<name> must equal form name
 
list=[1,2,3,4,5]
 
for SELECT use formencode.All(OneOf(list), Int())
 

	
 
"""
 
import logging
 

	
 
import formencode
 
from formencode import All
 

	
 
from pylons.i18n.translation import _
 

	
 
from rhodecode.model import validators as v
 
from rhodecode import BACKENDS
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class LoginForm(formencode.Schema):
 
    allow_extra_fields = True
 
    filter_extra_fields = True
 
    username = v.UnicodeString(
 
        strip=True,
 
        min=1,
 
        not_empty=True,
 
        messages={
 
           'empty': _(u'Please enter a login'),
 
           'tooShort': _(u'Enter a value %(min)i characters long or more')}
 
    )
 

	
 
    password = v.UnicodeString(
 
        strip=False,
 
        min=3,
 
        not_empty=True,
 
        messages={
 
            'empty': _(u'Please enter a password'),
 
            'tooShort': _(u'Enter %(min)i characters or more')}
 
    )
 

	
 
    remember = v.StringBoolean(if_missing=False)
 

	
 
    chained_validators = [v.ValidAuth()]
 

	
 

	
 
def UserForm(edit=False, old_data={}):
 
    class _UserForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 
        username = All(v.UnicodeString(strip=True, min=1, not_empty=True),
 
                       v.ValidUsername(edit, old_data))
 
        if edit:
 
            new_password = All(
 
                v.ValidPassword(),
 
                v.UnicodeString(strip=False, min=6, not_empty=False)
 
            )
 
            password_confirmation = All(
 
                v.ValidPassword(),
 
                v.UnicodeString(strip=False, min=6, not_empty=False),
 
            )
 
            admin = v.StringBoolean(if_missing=False)
 
        else:
 
            password = All(
 
                v.ValidPassword(),
 
                v.UnicodeString(strip=False, min=6, not_empty=True)
 
            )
 
            password_confirmation = All(
 
                v.ValidPassword(),
 
                v.UnicodeString(strip=False, min=6, not_empty=False)
 
            )
 

	
 
        active = v.StringBoolean(if_missing=False)
 
        firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
 
        lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
 
        email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
 

	
 
        chained_validators = [v.ValidPasswordsMatch()]
 

	
 
    return _UserForm
 

	
 

	
 
def UsersGroupForm(edit=False, old_data={}, available_members=[]):
 
    class _UsersGroupForm(formencode.Schema):
 
def UserGroupForm(edit=False, old_data={}, available_members=[]):
 
    class _UserGroupForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 

	
 
        users_group_name = All(
 
            v.UnicodeString(strip=True, min=1, not_empty=True),
 
            v.ValidUsersGroup(edit, old_data)
 
            v.ValidUserGroup(edit, old_data)
 
        )
 

	
 
        users_group_active = v.StringBoolean(if_missing=False)
 

	
 
        if edit:
 
            users_group_members = v.OneOf(
 
                available_members, hideList=False, testValueList=True,
 
                if_missing=None, not_empty=False
 
            )
 

	
 
    return _UsersGroupForm
 
    return _UserGroupForm
 

	
 

	
 
def ReposGroupForm(edit=False, old_data={}, available_groups=[],
 
                   can_create_in_root=False):
 
    class _ReposGroupForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 

	
 
        group_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
 
                               v.SlugifyName())
 
        group_description = v.UnicodeString(strip=True, min=1,
 
                                                not_empty=False)
 
        if edit:
 
            #FIXME: do a special check that we cannot move a group to one of
 
            #it's children
 
            pass
 
        group_parent_id = All(v.CanCreateGroup(can_create_in_root),
 
                              v.OneOf(available_groups, hideList=False,
 
                                      testValueList=True,
 
                                      if_missing=None, not_empty=True))
 
        enable_locking = v.StringBoolean(if_missing=False)
 
        recursive = v.StringBoolean(if_missing=False)
 
        chained_validators = [v.ValidReposGroup(edit, old_data),
 
                              v.ValidPerms('group')]
 

	
 
    return _ReposGroupForm
 

	
 

	
 
def RegisterForm(edit=False, old_data={}):
 
    class _RegisterForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 
        username = All(
 
            v.ValidUsername(edit, old_data),
 
            v.UnicodeString(strip=True, min=1, not_empty=True)
 
        )
 
        password = All(
 
            v.ValidPassword(),
 
            v.UnicodeString(strip=False, min=6, not_empty=True)
 
        )
 
        password_confirmation = All(
 
            v.ValidPassword(),
 
            v.UnicodeString(strip=False, min=6, not_empty=True)
 
        )
 
        active = v.StringBoolean(if_missing=False)
 
        firstname = v.UnicodeString(strip=True, min=1, not_empty=False)
 
        lastname = v.UnicodeString(strip=True, min=1, not_empty=False)
 
        email = All(v.Email(not_empty=True), v.UniqSystemEmail(old_data))
 

	
 
        chained_validators = [v.ValidPasswordsMatch()]
 

	
 
    return _RegisterForm
 

	
 

	
 
def PasswordResetForm():
 
    class _PasswordResetForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 
        email = All(v.ValidSystemEmail(), v.Email(not_empty=True))
 
    return _PasswordResetForm
 

	
 

	
 
def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
             repo_groups=[], landing_revs=[]):
 
    class _RepoForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = False
 
        repo_name = All(v.UnicodeString(strip=True, min=1, not_empty=True),
 
                        v.SlugifyName())
 
        repo_group = All(v.CanWriteGroup(),
 
                         v.OneOf(repo_groups, hideList=True))
 
        repo_type = v.OneOf(supported_backends)
 
        repo_description = v.UnicodeString(strip=True, min=1, not_empty=False)
 
        repo_private = v.StringBoolean(if_missing=False)
 
        repo_landing_rev = v.OneOf(landing_revs, hideList=True)
 
        clone_uri = All(v.UnicodeString(strip=True, min=1, not_empty=False))
 

	
 
        repo_enable_statistics = v.StringBoolean(if_missing=False)
 
        repo_enable_downloads = v.StringBoolean(if_missing=False)
 
        repo_enable_locking = v.StringBoolean(if_missing=False)
 

	
 
        if edit:
 
            #this is repo owner
 
            user = All(v.UnicodeString(not_empty=True), v.ValidRepoUser())
 

	
 
        chained_validators = [v.ValidCloneUri(),
 
                              v.ValidRepoName(edit, old_data),
 
                              v.ValidPerms()]
 
    return _RepoForm
 

	
 

	
 
def RepoFieldForm():
 
    class _RepoFieldForm(formencode.Schema):
 
        filter_extra_fields = True
 
        allow_extra_fields = True
 

	
rhodecode/model/repo.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.repo
 
    ~~~~~~~~~~~~~~~~~~~~
 

	
 
    Repository model for rhodecode
 

	
 
    :created_on: Jun 5, 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/>.
 
from __future__ import with_statement
 
import os
 
import shutil
 
import logging
 
import traceback
 
from datetime import datetime
 

	
 
from rhodecode.lib.vcs.backends import get_backend
 
from rhodecode.lib.compat import json
 
from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
 
    remove_prefix
 
from rhodecode.lib.caching_query import FromCache
 
from rhodecode.lib.hooks import log_create_repository, log_delete_repository
 

	
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
 
    Statistics, UsersGroup, UsersGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
 
    Statistics, UserGroup, UserGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
 
    RhodeCodeSetting, RepositoryField
 
from rhodecode.lib import helpers as h
 
from rhodecode.lib.auth import HasRepoPermissionAny
 
from rhodecode.lib.vcs.backends.base import EmptyChangeset
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class RepoModel(BaseModel):
 

	
 
    cls = Repository
 
    URL_SEPARATOR = Repository.url_sep()
 

	
 
    def __get_users_group(self, users_group):
 
        return self._get_instance(UsersGroup, users_group,
 
                                  callback=UsersGroup.get_by_group_name)
 
        return self._get_instance(UserGroup, users_group,
 
                                  callback=UserGroup.get_by_group_name)
 

	
 
    def _get_repos_group(self, repos_group):
 
        return self._get_instance(RepoGroup, repos_group,
 
                                  callback=RepoGroup.get_by_group_name)
 

	
 
    @LazyProperty
 
    def repos_path(self):
 
        """
 
        Get's the repositories root path from database
 
        """
 

	
 
        q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
 
        return q.ui_value
 

	
 
    def get(self, repo_id, cache=False):
 
        repo = self.sa.query(Repository)\
 
            .filter(Repository.repo_id == repo_id)
 

	
 
        if cache:
 
            repo = repo.options(FromCache("sql_cache_short",
 
                                          "get_repo_%s" % repo_id))
 
        return repo.scalar()
 

	
 
    def get_repo(self, repository):
 
        return self._get_repo(repository)
 

	
 
    def get_by_repo_name(self, repo_name, cache=False):
 
        repo = self.sa.query(Repository)\
 
            .filter(Repository.repo_name == repo_name)
 

	
 
        if cache:
 
            repo = repo.options(FromCache("sql_cache_short",
 
                                          "get_repo_%s" % repo_name))
 
        return repo.scalar()
 

	
 
    def get_all_user_repos(self, user):
 
        """
 
        Get's all repositories that user have at least read access
 

	
 
        :param user:
 
        :type user:
 
        """
 
        from rhodecode.lib.auth import AuthUser
 
        user = self._get_user(user)
 
        repos = AuthUser(user_id=user.user_id).permissions['repositories']
 
        access_check = lambda r: r[1] in ['repository.read',
 
                                          'repository.write',
 
                                          'repository.admin']
 
        repos = [x[0] for x in filter(access_check, repos.items())]
 
        return Repository.query().filter(Repository.repo_name.in_(repos))
 

	
 
    def get_users_js(self):
 
        users = self.sa.query(User).filter(User.active == True).all()
 
        return json.dumps([
 
            {
 
             'id': u.user_id,
 
             'fname': u.name,
 
             'lname': u.lastname,
 
             'nname': u.username,
 
             'gravatar_lnk': h.gravatar_url(u.email, 14)
 
            } for u in users]
 
        )
 

	
 
    def get_users_groups_js(self):
 
        users_groups = self.sa.query(UsersGroup)\
 
            .filter(UsersGroup.users_group_active == True).all()
 
        users_groups = self.sa.query(UserGroup)\
 
            .filter(UserGroup.users_group_active == True).all()
 

	
 
        return json.dumps([
 
            {
 
             'id': gr.users_group_id,
 
             'grname': gr.users_group_name,
 
             'grmembers': len(gr.members),
 
            } for gr in users_groups]
 
        )
 

	
 
    @classmethod
 
    def _render_datatable(cls, tmpl, *args, **kwargs):
 
        import rhodecode
 
        from pylons import tmpl_context as c
 
        from pylons.i18n.translation import _
 

	
 
        _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
 
        template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
 

	
 
        tmpl = template.get_def(tmpl)
 
        kwargs.update(dict(_=_, h=h, c=c))
 
        return tmpl.render(*args, **kwargs)
 

	
 
    @classmethod
 
    def update_repoinfo(cls, repositories=None):
 
        if not repositories:
 
            repositories = Repository.getAll()
 
        for repo in repositories:
 
            scm_repo = repo.scm_instance_no_cache
 
            last_cs = EmptyChangeset()
 
            if scm_repo:
 
                last_cs = scm_repo.get_changeset()
 
            repo.update_changeset_cache(last_cs)
 

	
 
    def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
 
                          super_user_actions=False):
 
        _render = self._render_datatable
 

	
 
        def quick_menu(repo_name):
 
            return _render('quick_menu', repo_name)
 

	
 
        def repo_lnk(name, rtype, private, fork_of):
 
            return _render('repo_name', name, rtype, private, fork_of,
 
                           short_name=not admin, admin=False)
 

	
 
        def last_change(last_change):
 
            return _render("last_change", last_change)
 

	
 
        def rss_lnk(repo_name):
 
            return _render("rss", repo_name)
 

	
 
        def atom_lnk(repo_name):
 
            return _render("atom", repo_name)
 

	
 
        def last_rev(repo_name, cs_cache):
 
            return _render('revision', repo_name, cs_cache.get('revision'),
 
                           cs_cache.get('raw_id'), cs_cache.get('author'),
 
                           cs_cache.get('message'))
 

	
 
        def desc(desc):
 
            from pylons import tmpl_context as c
 
            if c.visual.stylify_metatags:
 
                return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
 
            else:
 
                return h.urlify_text(h.truncate(desc, 60))
 

	
 
        def repo_actions(repo_name):
 
            return _render('repo_actions', repo_name, super_user_actions)
 

	
 
        def owner_actions(user_id, username):
 
            return _render('user_name', user_id, username)
 

	
 
        repos_data = []
 
        for repo in repos_list:
 
            if perm_check:
 
                # check permission at this level
 
                if not HasRepoPermissionAny(
 
                    'repository.read', 'repository.write', 'repository.admin'
 
                )(repo.repo_name, 'get_repos_as_dict check'):
 
                    continue
 
            cs_cache = repo.changeset_cache
 
            row = {
 
                "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),
 
                "last_changeset": last_rev(repo.repo_name, cs_cache),
 
                "raw_tip": cs_cache.get('revision'),
 
                "desc": desc(repo.description),
 
                "owner": h.person(repo.user.username),
 
                "rss": rss_lnk(repo.repo_name),
 
                "atom": atom_lnk(repo.repo_name),
 

	
 
            }
 
            if admin:
 
                row.update({
 
@@ -322,368 +322,368 @@ class RepoModel(BaseModel):
 
                    if strip:
 
                        k = remove_prefix(k, 'repo_')
 
                    setattr(cur_repo, k, val)
 

	
 
            new_name = cur_repo.get_new_name(kwargs['repo_name'])
 
            cur_repo.repo_name = new_name
 

	
 
            #handle extra fields
 
            for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
 
                k = RepositoryField.un_prefix_key(field)
 
                ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
 
                if ex_field:
 
                    ex_field.field_value = kwargs[field]
 
                    self.sa.add(ex_field)
 
            self.sa.add(cur_repo)
 

	
 
            if org_repo_name != new_name:
 
                # rename repository
 
                self.__rename_repo(old=org_repo_name, new=new_name)
 

	
 
            return cur_repo
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def create_repo(self, repo_name, repo_type, description, owner,
 
                    private=False, clone_uri=None, repos_group=None,
 
                    landing_rev='tip', just_db=False, fork_of=None,
 
                    copy_fork_permissions=False, enable_statistics=False,
 
                    enable_locking=False, enable_downloads=False):
 
        """
 
        Create repository
 

	
 
        """
 
        from rhodecode.model.scm import ScmModel
 

	
 
        owner = self._get_user(owner)
 
        fork_of = self._get_repo(fork_of)
 
        repos_group = self._get_repos_group(repos_group)
 
        try:
 

	
 
            # repo name is just a name of repository
 
            # while repo_name_full is a full qualified name that is combined
 
            # with name and path of group
 
            repo_name_full = repo_name
 
            repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
 

	
 
            new_repo = Repository()
 
            new_repo.enable_statistics = False
 
            new_repo.repo_name = repo_name_full
 
            new_repo.repo_type = repo_type
 
            new_repo.user = owner
 
            new_repo.group = repos_group
 
            new_repo.description = description or repo_name
 
            new_repo.private = private
 
            new_repo.clone_uri = clone_uri
 
            new_repo.landing_rev = landing_rev
 

	
 
            new_repo.enable_statistics = enable_statistics
 
            new_repo.enable_locking = enable_locking
 
            new_repo.enable_downloads = enable_downloads
 

	
 
            if repos_group:
 
                new_repo.enable_locking = repos_group.enable_locking
 

	
 
            if fork_of:
 
                parent_repo = fork_of
 
                new_repo.fork = parent_repo
 

	
 
            self.sa.add(new_repo)
 

	
 
            def _create_default_perms():
 
                # create default permission
 
                repo_to_perm = UserRepoToPerm()
 
                default = 'repository.read'
 
                for p in User.get_by_username('default').user_perms:
 
                    if p.permission.permission_name.startswith('repository.'):
 
                        default = p.permission.permission_name
 
                        break
 

	
 
                default_perm = 'repository.none' if private else default
 

	
 
                repo_to_perm.permission_id = self.sa.query(Permission)\
 
                        .filter(Permission.permission_name == default_perm)\
 
                        .one().permission_id
 

	
 
                repo_to_perm.repository = new_repo
 
                repo_to_perm.user_id = User.get_by_username('default').user_id
 

	
 
                self.sa.add(repo_to_perm)
 

	
 
            if fork_of:
 
                if copy_fork_permissions:
 
                    repo = fork_of
 
                    user_perms = UserRepoToPerm.query()\
 
                        .filter(UserRepoToPerm.repository == repo).all()
 
                    group_perms = UsersGroupRepoToPerm.query()\
 
                        .filter(UsersGroupRepoToPerm.repository == repo).all()
 
                    group_perms = UserGroupRepoToPerm.query()\
 
                        .filter(UserGroupRepoToPerm.repository == repo).all()
 

	
 
                    for perm in user_perms:
 
                        UserRepoToPerm.create(perm.user, new_repo,
 
                                              perm.permission)
 

	
 
                    for perm in group_perms:
 
                        UsersGroupRepoToPerm.create(perm.users_group, new_repo,
 
                        UserGroupRepoToPerm.create(perm.users_group, new_repo,
 
                                                    perm.permission)
 
                else:
 
                    _create_default_perms()
 
            else:
 
                _create_default_perms()
 

	
 
            if not just_db:
 
                self.__create_repo(repo_name, repo_type,
 
                                   repos_group,
 
                                   clone_uri)
 
                log_create_repository(new_repo.get_dict(),
 
                                      created_by=owner.username)
 

	
 
            # now automatically start following this repository as owner
 
            ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
 
                                                    owner.user_id)
 
            return new_repo
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def create(self, form_data, cur_user, just_db=False, fork=None):
 
        """
 
        Backward compatibility function, just a wrapper on top of create_repo
 

	
 
        :param form_data:
 
        :param cur_user:
 
        :param just_db:
 
        :param fork:
 
        """
 
        owner = cur_user
 
        repo_name = form_data['repo_name_full']
 
        repo_type = form_data['repo_type']
 
        description = form_data['repo_description']
 
        private = form_data['repo_private']
 
        clone_uri = form_data.get('clone_uri')
 
        repos_group = form_data['repo_group']
 
        landing_rev = form_data['repo_landing_rev']
 
        copy_fork_permissions = form_data.get('copy_permissions')
 
        fork_of = form_data.get('fork_parent_id')
 

	
 
        ## repo creation defaults, private and repo_type are filled in form
 
        defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
 
        enable_statistics = defs.get('repo_enable_statistics')
 
        enable_locking = defs.get('repo_enable_locking')
 
        enable_downloads = defs.get('repo_enable_downloads')
 

	
 
        return self.create_repo(
 
            repo_name, repo_type, description, owner, private, clone_uri,
 
            repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
 
            enable_statistics, enable_locking, enable_downloads
 
        )
 

	
 
    def create_fork(self, form_data, cur_user):
 
        """
 
        Simple wrapper into executing celery task for fork creation
 

	
 
        :param form_data:
 
        :param cur_user:
 
        """
 
        from rhodecode.lib.celerylib import tasks, run_task
 
        run_task(tasks.create_repo_fork, form_data, cur_user)
 

	
 
    def delete(self, repo):
 
        repo = self._get_repo(repo)
 
        if repo:
 
            old_repo_dict = repo.get_dict()
 
            owner = repo.user
 
            try:
 
                self.sa.delete(repo)
 
                self.__delete_repo(repo)
 
                log_delete_repository(old_repo_dict,
 
                                      deleted_by=owner.username)
 
            except:
 
                log.error(traceback.format_exc())
 
                raise
 

	
 
    def grant_user_permission(self, repo, user, perm):
 
        """
 
        Grant permission for user on given repository, or update existing one
 
        if found
 

	
 
        :param repo: Instance of Repository, repository_id, or repository name
 
        :param user: Instance of User, user_id or username
 
        :param perm: Instance of Permission, or permission_name
 
        """
 
        user = self._get_user(user)
 
        repo = self._get_repo(repo)
 
        permission = self._get_perm(perm)
 

	
 
        # check if we have that permission already
 
        obj = self.sa.query(UserRepoToPerm)\
 
            .filter(UserRepoToPerm.user == user)\
 
            .filter(UserRepoToPerm.repository == repo)\
 
            .scalar()
 
        if obj is None:
 
            # create new !
 
            obj = UserRepoToPerm()
 
        obj.repository = repo
 
        obj.user = user
 
        obj.permission = permission
 
        self.sa.add(obj)
 
        log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
 

	
 
    def revoke_user_permission(self, repo, user):
 
        """
 
        Revoke permission for user on given repository
 

	
 
        :param repo: Instance of Repository, repository_id, or repository name
 
        :param user: Instance of User, user_id or username
 
        """
 

	
 
        user = self._get_user(user)
 
        repo = self._get_repo(repo)
 

	
 
        obj = self.sa.query(UserRepoToPerm)\
 
            .filter(UserRepoToPerm.repository == repo)\
 
            .filter(UserRepoToPerm.user == user)\
 
            .scalar()
 
        if obj:
 
            self.sa.delete(obj)
 
            log.debug('Revoked perm on %s on %s' % (repo, user))
 

	
 
    def grant_users_group_permission(self, repo, group_name, perm):
 
        """
 
        Grant permission for user group on given repository, or update
 
        existing one if found
 

	
 
        :param repo: Instance of Repository, repository_id, or repository name
 
        :param group_name: Instance of UserGroup, users_group_id,
 
            or user group name
 
        :param perm: Instance of Permission, or permission_name
 
        """
 
        repo = self._get_repo(repo)
 
        group_name = self.__get_users_group(group_name)
 
        permission = self._get_perm(perm)
 

	
 
        # check if we have that permission already
 
        obj = self.sa.query(UsersGroupRepoToPerm)\
 
            .filter(UsersGroupRepoToPerm.users_group == group_name)\
 
            .filter(UsersGroupRepoToPerm.repository == repo)\
 
        obj = self.sa.query(UserGroupRepoToPerm)\
 
            .filter(UserGroupRepoToPerm.users_group == group_name)\
 
            .filter(UserGroupRepoToPerm.repository == repo)\
 
            .scalar()
 

	
 
        if obj is None:
 
            # create new
 
            obj = UsersGroupRepoToPerm()
 
            obj = UserGroupRepoToPerm()
 

	
 
        obj.repository = repo
 
        obj.users_group = group_name
 
        obj.permission = permission
 
        self.sa.add(obj)
 
        log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
 

	
 
    def revoke_users_group_permission(self, repo, group_name):
 
        """
 
        Revoke permission for user group on given repository
 

	
 
        :param repo: Instance of Repository, repository_id, or repository name
 
        :param group_name: Instance of UserGroup, users_group_id,
 
            or user group name
 
        """
 
        repo = self._get_repo(repo)
 
        group_name = self.__get_users_group(group_name)
 

	
 
        obj = self.sa.query(UsersGroupRepoToPerm)\
 
            .filter(UsersGroupRepoToPerm.repository == repo)\
 
            .filter(UsersGroupRepoToPerm.users_group == group_name)\
 
        obj = self.sa.query(UserGroupRepoToPerm)\
 
            .filter(UserGroupRepoToPerm.repository == repo)\
 
            .filter(UserGroupRepoToPerm.users_group == group_name)\
 
            .scalar()
 
        if obj:
 
            self.sa.delete(obj)
 
            log.debug('Revoked perm to %s on %s' % (repo, group_name))
 

	
 
    def delete_stats(self, repo_name):
 
        """
 
        removes stats for given repo
 

	
 
        :param repo_name:
 
        """
 
        repo = self._get_repo(repo_name)
 
        try:
 
            obj = self.sa.query(Statistics)\
 
                    .filter(Statistics.repository == repo).scalar()
 
            if obj:
 
                self.sa.delete(obj)
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def __create_repo(self, repo_name, alias, parent, clone_uri=False):
 
        """
 
        makes repository on filesystem. It's group aware means it'll create
 
        a repository within a group, and alter the paths accordingly of
 
        group location
 

	
 
        :param repo_name:
 
        :param alias:
 
        :param parent_id:
 
        :param clone_uri:
 
        """
 
        from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
 
        from rhodecode.model.scm import ScmModel
 

	
 
        if parent:
 
            new_parent_path = os.sep.join(parent.full_path_splitted)
 
        else:
 
            new_parent_path = ''
 

	
 
        # we need to make it str for mercurial
 
        repo_path = os.path.join(*map(lambda x: safe_str(x),
 
                                [self.repos_path, new_parent_path, repo_name]))
 

	
 
        # check if this path is not a repository
 
        if is_valid_repo(repo_path, self.repos_path):
 
            raise Exception('This path %s is a valid repository' % repo_path)
 

	
 
        # check if this path is a group
 
        if is_valid_repos_group(repo_path, self.repos_path):
 
            raise Exception('This path %s is a valid group' % repo_path)
 

	
 
        log.info('creating repo %s in %s @ %s' % (
 
                     repo_name, safe_unicode(repo_path), clone_uri
 
                )
 
        )
 
        backend = get_backend(alias)
 
        if alias == 'hg':
 
            backend(repo_path, create=True, src_url=clone_uri)
 
        elif alias == 'git':
 
            r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
 
            # add rhodecode hook into this repo
 
            ScmModel().install_git_hook(repo=r)
 
        else:
 
            raise Exception('Undefined alias %s' % alias)
 

	
 
    def __rename_repo(self, old, new):
 
        """
 
        renames repository on filesystem
 

	
 
        :param old: old name
 
        :param new: new name
 
        """
 
        log.info('renaming repo from %s to %s' % (old, new))
 

	
 
        old_path = os.path.join(self.repos_path, old)
 
        new_path = os.path.join(self.repos_path, new)
 
        if os.path.isdir(new_path):
 
            raise Exception(
 
                'Was trying to rename to already existing dir %s' % new_path
 
            )
 
        shutil.move(old_path, new_path)
 

	
 
    def __delete_repo(self, repo):
 
        """
 
        removes repo from filesystem, the removal is acctually made by
 
        added rm__ prefix into dir, and rename internat .hg/.git dirs so this
 
        repository is no longer valid for rhodecode, can be undeleted later on
 
        by reverting the renames on this repository
 

	
 
        :param repo: repo object
 
        """
 
        rm_path = os.path.join(self.repos_path, repo.repo_name)
 
        log.info("Removing %s" % (rm_path))
 
        # disable hg/git internal that it doesn't get detected as repo
 
        alias = repo.repo_type
rhodecode/model/repo_permission.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.users_group
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    repository permission model for RhodeCode
 

	
 
    :created_on: Oct 1, 2011
 
    :author: nvinot, marcink
 
    :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
 
    :copyright: (C) 2011-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/>.
 

	
 
import logging
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import UserRepoToPerm, UsersGroupRepoToPerm, \
 
from rhodecode.model.db import UserRepoToPerm, UserGroupRepoToPerm, \
 
    Permission
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class RepositoryPermissionModel(BaseModel):
 

	
 
    cls = UserRepoToPerm
 

	
 
    def get_user_permission(self, repository, user):
 
        repository = self._get_repo(repository)
 
        user = self._get_user(user)
 

	
 
        return UserRepoToPerm.query() \
 
                .filter(UserRepoToPerm.user == user) \
 
                .filter(UserRepoToPerm.repository == repository) \
 
                .scalar()
 

	
 
    def update_user_permission(self, repository, user, permission):
 
        permission = Permission.get_by_key(permission)
 
        current = self.get_user_permission(repository, user)
 
        if current:
 
            if not current.permission is permission:
 
                current.permission = permission
 
        else:
 
            p = UserRepoToPerm()
 
            p.user = user
 
            p.repository = repository
 
            p.permission = permission
 
            self.sa.add(p)
 

	
 
    def delete_user_permission(self, repository, user):
 
        current = self.get_user_permission(repository, user)
 
        if current:
 
            self.sa.delete(current)
 

	
 
    def get_users_group_permission(self, repository, users_group):
 
        return UsersGroupRepoToPerm.query() \
 
                .filter(UsersGroupRepoToPerm.users_group == users_group) \
 
                .filter(UsersGroupRepoToPerm.repository == repository) \
 
        return UserGroupRepoToPerm.query() \
 
                .filter(UserGroupRepoToPerm.users_group == users_group) \
 
                .filter(UserGroupRepoToPerm.repository == repository) \
 
                .scalar()
 

	
 
    def update_users_group_permission(self, repository, users_group,
 
                                      permission):
 
        permission = Permission.get_by_key(permission)
 
        current = self.get_users_group_permission(repository, users_group)
 
        if current:
 
            if not current.permission is permission:
 
                current.permission = permission
 
        else:
 
            p = UsersGroupRepoToPerm()
 
            p = UserGroupRepoToPerm()
 
            p.users_group = users_group
 
            p.repository = repository
 
            p.permission = permission
 
            self.sa.add(p)
 

	
 
    def delete_users_group_permission(self, repository, users_group):
 
        current = self.get_users_group_permission(repository, users_group)
 
        if current:
 
            self.sa.delete(current)
 

	
 
    def update_or_delete_user_permission(self, repository, user, permission):
 
        if permission:
 
            self.update_user_permission(repository, user, permission)
 
        else:
 
            self.delete_user_permission(repository, user)
 

	
 
    def update_or_delete_users_group_permission(self, repository, user_group,
 
                                              permission):
 
        if permission:
 
            self.update_users_group_permission(repository, user_group,
 
                                               permission)
 
        else:
 
            self.delete_users_group_permission(repository, user_group)
rhodecode/model/repos_group.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.user_group
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    repo group model for RhodeCode
 

	
 
    :created_on: Jan 25, 2011
 
    :author: marcink
 
    :copyright: (C) 2011-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/>.
 

	
 
import os
 
import logging
 
import traceback
 
import shutil
 
import datetime
 

	
 
from rhodecode.lib.utils2 import LazyProperty
 

	
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
 
    User, Permission, UsersGroupRepoGroupToPerm, UsersGroup, Repository
 
    User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class ReposGroupModel(BaseModel):
 

	
 
    cls = RepoGroup
 

	
 
    def __get_users_group(self, users_group):
 
        return self._get_instance(UsersGroup, users_group,
 
                                  callback=UsersGroup.get_by_group_name)
 
        return self._get_instance(UserGroup, users_group,
 
                                  callback=UserGroup.get_by_group_name)
 

	
 
    def _get_repos_group(self, repos_group):
 
        return self._get_instance(RepoGroup, repos_group,
 
                                  callback=RepoGroup.get_by_group_name)
 

	
 
    @LazyProperty
 
    def repos_path(self):
 
        """
 
        Get's the repositories root path from database
 
        """
 

	
 
        q = RhodeCodeUi.get_by_key('/')
 
        return q.ui_value
 

	
 
    def _create_default_perms(self, new_group):
 
        # create default permission
 
        repo_group_to_perm = UserRepoGroupToPerm()
 
        default_perm = 'group.read'
 
        for p in User.get_by_username('default').user_perms:
 
            if p.permission.permission_name.startswith('group.'):
 
                default_perm = p.permission.permission_name
 
                break
 

	
 
        repo_group_to_perm.permission_id = self.sa.query(Permission)\
 
                .filter(Permission.permission_name == default_perm)\
 
                .one().permission_id
 

	
 
        repo_group_to_perm.group = new_group
 
        repo_group_to_perm.user_id = User.get_by_username('default').user_id
 

	
 
        self.sa.add(repo_group_to_perm)
 

	
 
    def __create_group(self, group_name):
 
        """
 
        makes repository group on filesystem
 

	
 
        :param repo_name:
 
        :param parent_id:
 
        """
 

	
 
        create_path = os.path.join(self.repos_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, old, new):
 
        """
 
        Renames a group on filesystem
 

	
 
        :param group_name:
 
        """
 

	
 
        if old == new:
 
            log.debug('skipping group rename')
 
            return
 

	
 
        log.debug('renaming repos group from %s to %s' % (old, new))
 

	
 
        old_path = os.path.join(self.repos_path, old)
 
        new_path = os.path.join(self.repos_path, new)
 

	
 
        log.debug('renaming repos paths from %s to %s' % (old_path, new_path))
 

	
 
        if os.path.isdir(new_path):
 
            raise Exception('Was trying to rename to already '
 
                            'existing dir %s' % new_path)
 
        shutil.move(old_path, new_path)
 

	
 
    def __delete_group(self, group, force_delete=False):
 
        """
 
        Deletes a group from a filesystem
 

	
 
        :param group: instance of group from database
 
        :param force_delete: use shutil rmtree to remove all objects
 
        """
 
        paths = group.full_path.split(RepoGroup.url_sep())
 
        paths = os.sep.join(paths)
 

	
 
        rm_path = os.path.join(self.repos_path, paths)
 
        log.info("Removing group %s" % (rm_path))
 
        # delete only if that path really exists
 
        if os.path.isdir(rm_path):
 
            if force_delete:
 
                shutil.rmtree(rm_path)
 
            else:
 
                #archive that group`
 
                _now = datetime.datetime.now()
 
                _ms = str(_now.microsecond).rjust(6, '0')
 
                _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
 
                                          group.name)
 
                shutil.move(rm_path, os.path.join(self.repos_path, _d))
 

	
 
    def create(self, group_name, group_description, owner, parent=None, just_db=False):
 
@@ -297,130 +297,130 @@ class ReposGroupModel(BaseModel):
 
        :param recursive: recurse to all children of group
 
        """
 
        from rhodecode.model.repo import RepoModel
 
        repos_group = self._get_repos_group(repos_group)
 

	
 
        for el in repos_group.recursive_groups_and_repos():
 
            if not recursive:
 
                # if we don't recurse set the permission on only the top level
 
                # object
 
                el = repos_group
 

	
 
            if isinstance(el, RepoGroup):
 
                if obj_type == 'user':
 
                    ReposGroupModel().revoke_user_permission(el, user=obj)
 
                elif obj_type == 'users_group':
 
                    ReposGroupModel().revoke_users_group_permission(el, group_name=obj)
 
                else:
 
                    raise Exception('undefined object type %s' % obj_type)
 
            elif isinstance(el, Repository):
 
                if obj_type == 'user':
 
                    RepoModel().revoke_user_permission(el, user=obj)
 
                elif obj_type == 'users_group':
 
                    RepoModel().revoke_users_group_permission(el, group_name=obj)
 
                else:
 
                    raise Exception('undefined object type %s' % obj_type)
 

	
 
            #if it's not recursive call
 
            # break the loop and don't proceed with other changes
 
            if not recursive:
 
                break
 

	
 
    def grant_user_permission(self, repos_group, user, perm):
 
        """
 
        Grant permission for user on given repository group, or update
 
        existing one if found
 

	
 
        :param repos_group: Instance of ReposGroup, repositories_group_id,
 
            or repositories_group name
 
        :param user: Instance of User, user_id or username
 
        :param perm: Instance of Permission, or permission_name
 
        """
 

	
 
        repos_group = self._get_repos_group(repos_group)
 
        user = self._get_user(user)
 
        permission = self._get_perm(perm)
 

	
 
        # check if we have that permission already
 
        obj = self.sa.query(UserRepoGroupToPerm)\
 
            .filter(UserRepoGroupToPerm.user == user)\
 
            .filter(UserRepoGroupToPerm.group == repos_group)\
 
            .scalar()
 
        if obj is None:
 
            # create new !
 
            obj = UserRepoGroupToPerm()
 
        obj.group = repos_group
 
        obj.user = user
 
        obj.permission = permission
 
        self.sa.add(obj)
 
        log.debug('Granted perm %s to %s on %s' % (perm, user, repos_group))
 

	
 
    def revoke_user_permission(self, repos_group, user):
 
        """
 
        Revoke permission for user on given repository group
 

	
 
        :param repos_group: Instance of ReposGroup, repositories_group_id,
 
            or repositories_group name
 
        :param user: Instance of User, user_id or username
 
        """
 

	
 
        repos_group = self._get_repos_group(repos_group)
 
        user = self._get_user(user)
 

	
 
        obj = self.sa.query(UserRepoGroupToPerm)\
 
            .filter(UserRepoGroupToPerm.user == user)\
 
            .filter(UserRepoGroupToPerm.group == repos_group)\
 
            .scalar()
 
        if obj:
 
            self.sa.delete(obj)
 
            log.debug('Revoked perm on %s on %s' % (repos_group, user))
 

	
 
    def grant_users_group_permission(self, repos_group, group_name, perm):
 
        """
 
        Grant permission for user group on given repository group, or update
 
        existing one if found
 

	
 
        :param repos_group: Instance of ReposGroup, repositories_group_id,
 
            or repositories_group name
 
        :param group_name: Instance of UserGroup, users_group_id,
 
            or user group name
 
        :param perm: Instance of Permission, or permission_name
 
        """
 
        repos_group = self._get_repos_group(repos_group)
 
        group_name = self.__get_users_group(group_name)
 
        permission = self._get_perm(perm)
 

	
 
        # check if we have that permission already
 
        obj = self.sa.query(UsersGroupRepoGroupToPerm)\
 
            .filter(UsersGroupRepoGroupToPerm.group == repos_group)\
 
            .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\
 
        obj = self.sa.query(UserGroupRepoGroupToPerm)\
 
            .filter(UserGroupRepoGroupToPerm.group == repos_group)\
 
            .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
 
            .scalar()
 

	
 
        if obj is None:
 
            # create new
 
            obj = UsersGroupRepoGroupToPerm()
 
            obj = UserGroupRepoGroupToPerm()
 

	
 
        obj.group = repos_group
 
        obj.users_group = group_name
 
        obj.permission = permission
 
        self.sa.add(obj)
 
        log.debug('Granted perm %s to %s on %s' % (perm, group_name, repos_group))
 

	
 
    def revoke_users_group_permission(self, repos_group, group_name):
 
        """
 
        Revoke permission for user group on given repository group
 

	
 
        :param repos_group: Instance of ReposGroup, repositories_group_id,
 
            or repositories_group name
 
        :param group_name: Instance of UserGroup, users_group_id,
 
            or user group name
 
        """
 
        repos_group = self._get_repos_group(repos_group)
 
        group_name = self.__get_users_group(group_name)
 

	
 
        obj = self.sa.query(UsersGroupRepoGroupToPerm)\
 
            .filter(UsersGroupRepoGroupToPerm.group == repos_group)\
 
            .filter(UsersGroupRepoGroupToPerm.users_group == group_name)\
 
        obj = self.sa.query(UserGroupRepoGroupToPerm)\
 
            .filter(UserGroupRepoGroupToPerm.group == repos_group)\
 
            .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
 
            .scalar()
 
        if obj:
 
            self.sa.delete(obj)
 
            log.debug('Revoked perm to %s on %s' % (repos_group, group_name))
rhodecode/model/user.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.user
 
    ~~~~~~~~~~~~~~~~~~~~
 

	
 
    users model for RhodeCode
 

	
 
    :created_on: Apr 9, 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/>.
 

	
 
import logging
 
import traceback
 
import itertools
 
import collections
 
from pylons import url
 
from pylons.i18n.translation import _
 

	
 
from sqlalchemy.exc import DatabaseError
 
from sqlalchemy.orm import joinedload
 

	
 
from rhodecode.lib.utils2 import safe_unicode, generate_api_key
 
from rhodecode.lib.caching_query import FromCache
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
 
    UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \
 
    Notification, RepoGroup, UserRepoGroupToPerm, UsersGroupRepoGroupToPerm, \
 
    UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \
 
    Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \
 
    UserEmailMap, UserIpMap
 
from rhodecode.lib.exceptions import DefaultUserException, \
 
    UserOwnsReposException
 
from rhodecode.model.meta import Session
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
PERM_WEIGHTS = Permission.PERM_WEIGHTS
 

	
 

	
 
class UserModel(BaseModel):
 
    cls = User
 

	
 
    def get(self, user_id, cache=False):
 
        user = self.sa.query(User)
 
        if cache:
 
            user = user.options(FromCache("sql_cache_short",
 
                                          "get_user_%s" % user_id))
 
        return user.get(user_id)
 

	
 
    def get_user(self, user):
 
        return self._get_user(user)
 

	
 
    def get_by_username(self, username, cache=False, case_insensitive=False):
 

	
 
        if case_insensitive:
 
            user = self.sa.query(User).filter(User.username.ilike(username))
 
        else:
 
            user = self.sa.query(User)\
 
                .filter(User.username == username)
 
        if cache:
 
            user = user.options(FromCache("sql_cache_short",
 
                                          "get_user_%s" % username))
 
        return user.scalar()
 

	
 
    def get_by_email(self, email, cache=False, case_insensitive=False):
 
        return User.get_by_email(email, case_insensitive, cache)
 

	
 
    def get_by_api_key(self, api_key, cache=False):
 
        return User.get_by_api_key(api_key, cache)
 

	
 
    def create(self, form_data):
 
        from rhodecode.lib.auth import get_crypt_password
 
        try:
 
            new_user = User()
 
            for k, v in form_data.items():
 
                if k == 'password':
 
                    v = get_crypt_password(v)
 
                if k == 'firstname':
 
                    k = 'name'
 
                setattr(new_user, k, v)
 

	
 
            new_user.api_key = generate_api_key(form_data['username'])
 
            self.sa.add(new_user)
 
            return new_user
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def create_or_update(self, username, password, email, firstname='',
 
                         lastname='', active=True, admin=False, ldap_dn=None):
 
        """
 
        Creates a new instance if not found, or updates current one
 

	
 
        :param username:
 
        :param password:
 
        :param email:
 
        :param active:
 
        :param firstname:
 
        :param lastname:
 
        :param active:
 
        :param admin:
 
        :param ldap_dn:
 
        """
 

	
 
        from rhodecode.lib.auth import get_crypt_password
 

	
 
        log.debug('Checking for %s account in RhodeCode database' % username)
 
        user = User.get_by_username(username, case_insensitive=True)
 
        if user is None:
 
            log.debug('creating new user %s' % username)
 
            new_user = User()
 
            edit = False
 
        else:
 
            log.debug('updating user %s' % username)
 
            new_user = user
 
            edit = True
 

	
 
        try:
 
            new_user.username = username
 
            new_user.admin = admin
 
            # set password only if creating an user or password is changed
 
            if edit is False or user.password != password:
 
                new_user.password = get_crypt_password(password)
 
                new_user.api_key = generate_api_key(username)
 
@@ -420,310 +420,310 @@ class UserModel(BaseModel):
 
            make decision based on the algo
 
        :param algo: algorithm to decide what permission should be choose if
 
            it's multiple defined, eg user in two different groups. It also
 
            decides if explicit flag is turned off how to specify the permission
 
            for case when user is in a group + have defined separate permission
 
        """
 
        RK = 'repositories'
 
        GK = 'repositories_groups'
 
        GLOBAL = 'global'
 
        user.permissions[RK] = {}
 
        user.permissions[GK] = {}
 
        user.permissions[GLOBAL] = set()
 

	
 
        def _choose_perm(new_perm, cur_perm):
 
            new_perm_val = PERM_WEIGHTS[new_perm]
 
            cur_perm_val = PERM_WEIGHTS[cur_perm]
 
            if algo == 'higherwin':
 
                if new_perm_val > cur_perm_val:
 
                    return new_perm
 
                return cur_perm
 
            elif algo == 'lowerwin':
 
                if new_perm_val < cur_perm_val:
 
                    return new_perm
 
                return cur_perm
 

	
 
        #======================================================================
 
        # fetch default permissions
 
        #======================================================================
 
        default_user = User.get_by_username('default', cache=True)
 
        default_user_id = default_user.user_id
 

	
 
        default_repo_perms = Permission.get_default_perms(default_user_id)
 
        default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
 

	
 
        if user.is_admin:
 
            #==================================================================
 
            # admin user have all default rights for repositories
 
            # and groups set to admin
 
            #==================================================================
 
            user.permissions[GLOBAL].add('hg.admin')
 

	
 
            # repositories
 
            for perm in default_repo_perms:
 
                r_k = perm.UserRepoToPerm.repository.repo_name
 
                p = 'repository.admin'
 
                user.permissions[RK][r_k] = p
 

	
 
            # repository groups
 
            for perm in default_repo_groups_perms:
 
                rg_k = perm.UserRepoGroupToPerm.group.group_name
 
                p = 'group.admin'
 
                user.permissions[GK][rg_k] = p
 
            return user
 

	
 
        #==================================================================
 
        # SET DEFAULTS GLOBAL, REPOS, REPOS GROUPS
 
        #==================================================================
 
        uid = user.user_id
 

	
 
        # default global permissions taken fron the default user
 
        default_global_perms = self.sa.query(UserToPerm)\
 
            .filter(UserToPerm.user_id == default_user_id)
 

	
 
        for perm in default_global_perms:
 
            user.permissions[GLOBAL].add(perm.permission.permission_name)
 

	
 
        # defaults for repositories, taken from default user
 
        for perm in default_repo_perms:
 
            r_k = perm.UserRepoToPerm.repository.repo_name
 
            if perm.Repository.private and not (perm.Repository.user_id == uid):
 
                # disable defaults for private repos,
 
                p = 'repository.none'
 
            elif perm.Repository.user_id == uid:
 
                # set admin if owner
 
                p = 'repository.admin'
 
            else:
 
                p = perm.Permission.permission_name
 

	
 
            user.permissions[RK][r_k] = p
 

	
 
        # defaults for repository groups taken from default user permission
 
        # on given group
 
        for perm in default_repo_groups_perms:
 
            rg_k = perm.UserRepoGroupToPerm.group.group_name
 
            p = perm.Permission.permission_name
 
            user.permissions[GK][rg_k] = p
 

	
 
        #======================================================================
 
        # !! OVERRIDE GLOBALS !! with user permissions if any found
 
        #======================================================================
 
        # those can be configured from groups or users explicitly
 
        _configurable = set(['hg.fork.none', 'hg.fork.repository',
 
                             'hg.create.none', 'hg.create.repository'])
 

	
 
        # USER GROUPS comes first
 
        # user group global permissions
 
        user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
 
            .options(joinedload(UsersGroupToPerm.permission))\
 
            .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
 
                   UsersGroupMember.users_group_id))\
 
            .filter(UsersGroupMember.user_id == uid)\
 
            .order_by(UsersGroupToPerm.users_group_id)\
 
        user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\
 
            .options(joinedload(UserGroupToPerm.permission))\
 
            .join((UserGroupMember, UserGroupToPerm.users_group_id ==
 
                   UserGroupMember.users_group_id))\
 
            .filter(UserGroupMember.user_id == uid)\
 
            .order_by(UserGroupToPerm.users_group_id)\
 
            .all()
 
        #need to group here by groups since user can be in more than one group
 
        _grouped = [[x, list(y)] for x, y in
 
                    itertools.groupby(user_perms_from_users_groups,
 
                                      lambda x:x.users_group)]
 
        for gr, perms in _grouped:
 
            # since user can be in multiple groups iterate over them and
 
            # select the lowest permissions first (more explicit)
 
            ##TODO: do this^^
 
            if not gr.inherit_default_permissions:
 
                # NEED TO IGNORE all configurable permissions and
 
                # replace them with explicitly set
 
                user.permissions[GLOBAL] = user.permissions[GLOBAL]\
 
                                                .difference(_configurable)
 
            for perm in perms:
 
                user.permissions[GLOBAL].add(perm.permission.permission_name)
 

	
 
        # user specific global permissions
 
        user_perms = self.sa.query(UserToPerm)\
 
                .options(joinedload(UserToPerm.permission))\
 
                .filter(UserToPerm.user_id == uid).all()
 

	
 
        if not user.inherit_default_permissions:
 
            # NEED TO IGNORE all configurable permissions and
 
            # replace them with explicitly set
 
            user.permissions[GLOBAL] = user.permissions[GLOBAL]\
 
                                            .difference(_configurable)
 

	
 
            for perm in user_perms:
 
                user.permissions[GLOBAL].add(perm.permission.permission_name)
 

	
 
        #======================================================================
 
        # !! PERMISSIONS FOR REPOSITORIES !!
 
        #======================================================================
 
        #======================================================================
 
        # check if user is part of user groups for this repository and
 
        # fill in his permission from it. _choose_perm decides of which
 
        # permission should be selected based on selected method
 
        #======================================================================
 

	
 
        # user group for repositories permissions
 
        user_repo_perms_from_users_groups = \
 
         self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
 
            .join((Repository, UsersGroupRepoToPerm.repository_id ==
 
         self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\
 
            .join((Repository, UserGroupRepoToPerm.repository_id ==
 
                   Repository.repo_id))\
 
            .join((Permission, UsersGroupRepoToPerm.permission_id ==
 
            .join((Permission, UserGroupRepoToPerm.permission_id ==
 
                   Permission.permission_id))\
 
            .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
 
                   UsersGroupMember.users_group_id))\
 
            .filter(UsersGroupMember.user_id == uid)\
 
            .join((UserGroupMember, UserGroupRepoToPerm.users_group_id ==
 
                   UserGroupMember.users_group_id))\
 
            .filter(UserGroupMember.user_id == uid)\
 
            .all()
 

	
 
        multiple_counter = collections.defaultdict(int)
 
        for perm in user_repo_perms_from_users_groups:
 
            r_k = perm.UsersGroupRepoToPerm.repository.repo_name
 
            r_k = perm.UserGroupRepoToPerm.repository.repo_name
 
            multiple_counter[r_k] += 1
 
            p = perm.Permission.permission_name
 
            cur_perm = user.permissions[RK][r_k]
 

	
 
            if perm.Repository.user_id == uid:
 
                # set admin if owner
 
                p = 'repository.admin'
 
            else:
 
                if multiple_counter[r_k] > 1:
 
                    p = _choose_perm(p, cur_perm)
 
            user.permissions[RK][r_k] = p
 

	
 
        # user explicit permissions for repositories, overrides any specified
 
        # by the group permission
 
        user_repo_perms = \
 
         self.sa.query(UserRepoToPerm, Permission, Repository)\
 
            .join((Repository, UserRepoToPerm.repository_id ==
 
                   Repository.repo_id))\
 
            .join((Permission, UserRepoToPerm.permission_id ==
 
                   Permission.permission_id))\
 
            .filter(UserRepoToPerm.user_id == uid)\
 
            .all()
 

	
 
        for perm in user_repo_perms:
 
            r_k = perm.UserRepoToPerm.repository.repo_name
 
            cur_perm = user.permissions[RK][r_k]
 
            # set admin if owner
 
            if perm.Repository.user_id == uid:
 
                p = 'repository.admin'
 
            else:
 
                p = perm.Permission.permission_name
 
                if not explicit:
 
                    p = _choose_perm(p, cur_perm)
 
            user.permissions[RK][r_k] = p
 

	
 
        #======================================================================
 
        # !! PERMISSIONS FOR REPOSITORY GROUPS !!
 
        #======================================================================
 
        #======================================================================
 
        # check if user is part of user groups for this repository groups and
 
        # fill in his permission from it. _choose_perm decides of which
 
        # permission should be selected based on selected method
 
        #======================================================================
 
        # user group for repo groups permissions
 
        user_repo_group_perms_from_users_groups = \
 
         self.sa.query(UsersGroupRepoGroupToPerm, Permission, RepoGroup)\
 
         .join((RepoGroup, UsersGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((Permission, UsersGroupRepoGroupToPerm.permission_id
 
         self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\
 
         .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((Permission, UserGroupRepoGroupToPerm.permission_id
 
                == Permission.permission_id))\
 
         .join((UsersGroupMember, UsersGroupRepoGroupToPerm.users_group_id
 
                == UsersGroupMember.users_group_id))\
 
         .filter(UsersGroupMember.user_id == uid)\
 
         .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id
 
                == UserGroupMember.users_group_id))\
 
         .filter(UserGroupMember.user_id == uid)\
 
         .all()
 

	
 
        multiple_counter = collections.defaultdict(int)
 
        for perm in user_repo_group_perms_from_users_groups:
 
            g_k = perm.UsersGroupRepoGroupToPerm.group.group_name
 
            g_k = perm.UserGroupRepoGroupToPerm.group.group_name
 
            multiple_counter[g_k] += 1
 
            p = perm.Permission.permission_name
 
            cur_perm = user.permissions[GK][g_k]
 
            if multiple_counter[g_k] > 1:
 
                p = _choose_perm(p, cur_perm)
 
            user.permissions[GK][g_k] = p
 

	
 
        # user explicit permissions for repository groups
 
        user_repo_groups_perms = \
 
         self.sa.query(UserRepoGroupToPerm, Permission, RepoGroup)\
 
         .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
 
         .join((Permission, UserRepoGroupToPerm.permission_id
 
                == Permission.permission_id))\
 
         .filter(UserRepoGroupToPerm.user_id == uid)\
 
         .all()
 

	
 
        for perm in user_repo_groups_perms:
 
            rg_k = perm.UserRepoGroupToPerm.group.group_name
 
            p = perm.Permission.permission_name
 
            cur_perm = user.permissions[GK][rg_k]
 
            if not explicit:
 
                p = _choose_perm(p, cur_perm)
 
            user.permissions[GK][rg_k] = p
 

	
 
        return user
 

	
 
    def has_perm(self, user, perm):
 
        perm = self._get_perm(perm)
 
        user = self._get_user(user)
 

	
 
        return UserToPerm.query().filter(UserToPerm.user == user)\
 
            .filter(UserToPerm.permission == perm).scalar() is not None
 

	
 
    def grant_perm(self, user, perm):
 
        """
 
        Grant user global permissions
 

	
 
        :param user:
 
        :param perm:
 
        """
 
        user = self._get_user(user)
 
        perm = self._get_perm(perm)
 
        # if this permission is already granted skip it
 
        _perm = UserToPerm.query()\
 
            .filter(UserToPerm.user == user)\
 
            .filter(UserToPerm.permission == perm)\
 
            .scalar()
 
        if _perm:
 
            return
 
        new = UserToPerm()
 
        new.user = user
 
        new.permission = perm
 
        self.sa.add(new)
 

	
 
    def revoke_perm(self, user, perm):
 
        """
 
        Revoke users global permissions
 

	
 
        :param user:
 
        :param perm:
 
        """
 
        user = self._get_user(user)
 
        perm = self._get_perm(perm)
 

	
 
        obj = UserToPerm.query()\
 
                .filter(UserToPerm.user == user)\
 
                .filter(UserToPerm.permission == perm)\
 
                .scalar()
 
        if obj:
 
            self.sa.delete(obj)
 

	
 
    def add_extra_email(self, user, email):
 
        """
 
        Adds email address to UserEmailMap
 

	
 
        :param user:
 
        :param email:
 
        """
 
        from rhodecode.model import forms
 
        form = forms.UserExtraEmailForm()()
 
        data = form.to_python(dict(email=email))
 
        user = self._get_user(user)
 

	
 
        obj = UserEmailMap()
 
        obj.user = user
 
        obj.email = data['email']
 
        self.sa.add(obj)
 
        return obj
 

	
 
    def delete_extra_email(self, user, email_id):
 
        """
 
        Removes email address from UserEmailMap
 

	
 
        :param user:
 
        :param email_id:
 
        """
rhodecode/model/users_group.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
"""
 
    rhodecode.model.users_group
 
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

	
 
    user group model for RhodeCode
 

	
 
    :created_on: Oct 1, 2011
 
    :author: nvinot
 
    :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
 
    :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/>.
 

	
 
import logging
 
import traceback
 

	
 
from rhodecode.model import BaseModel
 
from rhodecode.model.db import UsersGroupMember, UsersGroup,\
 
    UsersGroupRepoToPerm, Permission, UsersGroupToPerm, User
 
from rhodecode.lib.exceptions import UsersGroupsAssignedException
 
from rhodecode.model.db import UserGroupMember, UserGroup,\
 
    UserGroupRepoToPerm, Permission, UserGroupToPerm, User
 
from rhodecode.lib.exceptions import UserGroupsAssignedException
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UsersGroupModel(BaseModel):
 
class UserGroupModel(BaseModel):
 

	
 
    cls = UsersGroup
 
    cls = UserGroup
 

	
 
    def __get_users_group(self, users_group):
 
        return self._get_instance(UsersGroup, users_group,
 
                                  callback=UsersGroup.get_by_group_name)
 
        return self._get_instance(UserGroup, users_group,
 
                                  callback=UserGroup.get_by_group_name)
 

	
 
    def get(self, users_group_id, cache=False):
 
        return UsersGroup.get(users_group_id)
 
        return UserGroup.get(users_group_id)
 

	
 
    def get_group(self, users_group):
 
        return self.__get_users_group(users_group)
 

	
 
    def get_by_name(self, name, cache=False, case_insensitive=False):
 
        return UsersGroup.get_by_group_name(name, cache, case_insensitive)
 
        return UserGroup.get_by_group_name(name, cache, case_insensitive)
 

	
 
    def create(self, name, active=True):
 
        try:
 
            new = UsersGroup()
 
            new = UserGroup()
 
            new.users_group_name = name
 
            new.users_group_active = active
 
            self.sa.add(new)
 
            return new
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def update(self, users_group, form_data):
 

	
 
        try:
 
            users_group = self.__get_users_group(users_group)
 

	
 
            for k, v in form_data.items():
 
                if k == 'users_group_members':
 
                    users_group.members = []
 
                    self.sa.flush()
 
                    members_list = []
 
                    if v:
 
                        v = [v] if isinstance(v, basestring) else v
 
                        for u_id in set(v):
 
                            member = UsersGroupMember(users_group.users_group_id, u_id)
 
                            member = UserGroupMember(users_group.users_group_id, u_id)
 
                            members_list.append(member)
 
                    setattr(users_group, 'members', members_list)
 
                setattr(users_group, k, v)
 

	
 
            self.sa.add(users_group)
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def delete(self, users_group, force=False):
 
        """
 
        Deletes repos group, unless force flag is used
 
        raises exception if there are members in that group, else deletes
 
        group and users
 

	
 
        :param users_group:
 
        :param force:
 
        """
 
        try:
 
            users_group = self.__get_users_group(users_group)
 

	
 
            # check if this group is not assigned to repo
 
            assigned_groups = UsersGroupRepoToPerm.query()\
 
                .filter(UsersGroupRepoToPerm.users_group == users_group).all()
 
            assigned_groups = UserGroupRepoToPerm.query()\
 
                .filter(UserGroupRepoToPerm.users_group == users_group).all()
 

	
 
            if assigned_groups and force is False:
 
                raise UsersGroupsAssignedException('RepoGroup assigned to %s' %
 
                raise UserGroupsAssignedException('RepoGroup assigned to %s' %
 
                                                   assigned_groups)
 

	
 
            self.sa.delete(users_group)
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def add_user_to_group(self, users_group, user):
 
        users_group = self.__get_users_group(users_group)
 
        user = self._get_user(user)
 

	
 
        for m in users_group.members:
 
            u = m.user
 
            if u.user_id == user.user_id:
 
                return True
 

	
 
        try:
 
            users_group_member = UsersGroupMember()
 
            users_group_member = UserGroupMember()
 
            users_group_member.user = user
 
            users_group_member.users_group = users_group
 

	
 
            users_group.members.append(users_group_member)
 
            user.group_member.append(users_group_member)
 

	
 
            self.sa.add(users_group_member)
 
            return users_group_member
 
        except:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def remove_user_from_group(self, users_group, user):
 
        users_group = self.__get_users_group(users_group)
 
        user = self._get_user(user)
 

	
 
        users_group_member = None
 
        for m in users_group.members:
 
            if m.user.user_id == user.user_id:
 
                # Found this user's membership row
 
                users_group_member = m
 
                break
 

	
 
        if users_group_member:
 
            try:
 
                self.sa.delete(users_group_member)
 
                return True
 
            except:
 
                log.error(traceback.format_exc())
 
                raise
 
        else:
 
            # User isn't in that group
 
            return False
 

	
 
    def has_perm(self, users_group, perm):
 
        users_group = self.__get_users_group(users_group)
 
        perm = self._get_perm(perm)
 

	
 
        return UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == users_group)\
 
            .filter(UsersGroupToPerm.permission == perm).scalar() is not None
 
        return UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == users_group)\
 
            .filter(UserGroupToPerm.permission == perm).scalar() is not None
 

	
 
    def grant_perm(self, users_group, perm):
 
        users_group = self.__get_users_group(users_group)
 
        perm = self._get_perm(perm)
 

	
 
        # if this permission is already granted skip it
 
        _perm = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == users_group)\
 
            .filter(UsersGroupToPerm.permission == perm)\
 
        _perm = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == users_group)\
 
            .filter(UserGroupToPerm.permission == perm)\
 
            .scalar()
 
        if _perm:
 
            return
 

	
 
        new = UsersGroupToPerm()
 
        new = UserGroupToPerm()
 
        new.users_group = users_group
 
        new.permission = perm
 
        self.sa.add(new)
 

	
 
    def revoke_perm(self, users_group, perm):
 
        users_group = self.__get_users_group(users_group)
 
        perm = self._get_perm(perm)
 

	
 
        obj = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == users_group)\
 
            .filter(UsersGroupToPerm.permission == perm).scalar()
 
        obj = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == users_group)\
 
            .filter(UserGroupToPerm.permission == perm).scalar()
 
        if obj:
 
            self.sa.delete(obj)
rhodecode/model/validators.py
Show inline comments
 
"""
 
Set of generic validators
 
"""
 
import os
 
import re
 
import formencode
 
import logging
 
from collections import defaultdict
 
from pylons.i18n.translation import _
 
from webhelpers.pylonslib.secure_form import authentication_token
 

	
 
from formencode.validators import (
 
    UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set,
 
    NotEmpty, IPAddress, CIDR
 
)
 
from rhodecode.lib.compat import OrderedSet
 
from rhodecode.lib import ipaddr
 
from rhodecode.lib.utils import repo_name_slug
 
from rhodecode.model.db import RepoGroup, Repository, UsersGroup, User,\
 
from rhodecode.model.db import RepoGroup, Repository, UserGroup, User,\
 
    ChangesetStatus
 
from rhodecode.lib.exceptions import LdapImportError
 
from rhodecode.config.routing import ADMIN_PREFIX
 
from rhodecode.lib.auth import HasReposGroupPermissionAny, HasPermissionAny
 

	
 
# silence warnings and pylint
 
UnicodeString, OneOf, Int, Number, Regex, Email, Bool, StringBoolean, Set, \
 
    NotEmpty, IPAddress, CIDR
 

	
 
log = logging.getLogger(__name__)
 

	
 

	
 
class UniqueList(formencode.FancyValidator):
 
    """
 
    Unique List !
 
    """
 
    messages = dict(
 
        empty=_('Value cannot be an empty list'),
 
        missing_value=_('Value cannot be an empty list'),
 
    )
 

	
 
    def _to_python(self, value, state):
 
        if isinstance(value, list):
 
            return value
 
        elif isinstance(value, set):
 
            return list(value)
 
        elif isinstance(value, tuple):
 
            return list(value)
 
        elif value is None:
 
            return []
 
        else:
 
            return [value]
 

	
 
    def empty_value(self, value):
 
        return []
 

	
 

	
 
class StateObj(object):
 
    """
 
    this is needed to translate the messages using _() in validators
 
    """
 
    _ = staticmethod(_)
 

	
 

	
 
def M(self, key, state=None, **kwargs):
 
    """
 
    returns string from self.message based on given key,
 
    passed kw params are used to substitute %(named)s params inside
 
    translated strings
 

	
 
    :param msg:
 
    :param state:
 
    """
 
    if state is None:
 
        state = StateObj()
 
    else:
 
        state._ = staticmethod(_)
 
    #inject validator into state object
 
    return self.message(key, state, **kwargs)
 

	
 

	
 
def ValidUsername(edit=False, old_data={}):
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'username_exists': _(u'Username "%(username)s" already exists'),
 
            'system_invalid_username':
 
                _(u'Username "%(username)s" is forbidden'),
 
            'invalid_username':
 
                _(u'Username may only contain alphanumeric characters '
 
                  'underscores, periods or dashes and must begin with '
 
                  'alphanumeric character')
 
        }
 

	
 
        def validate_python(self, value, state):
 
            if value in ['default', 'new_user']:
 
                msg = M(self, 'system_invalid_username', state, username=value)
 
                raise formencode.Invalid(msg, value, state)
 
            #check if user is unique
 
            old_un = None
 
            if edit:
 
                old_un = User.get(old_data.get('user_id')).username
 

	
 
            if old_un != value or not edit:
 
                if User.get_by_username(value, case_insensitive=True):
 
                    msg = M(self, 'username_exists', state, username=value)
 
                    raise formencode.Invalid(msg, value, state)
 

	
 
            if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]*$', value) is None:
 
                msg = M(self, 'invalid_username', state)
 
                raise formencode.Invalid(msg, value, state)
 
    return _validator
 

	
 

	
 
def ValidRepoUser():
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'invalid_username': _(u'Username %(username)s is not valid')
 
        }
 

	
 
        def validate_python(self, value, state):
 
            try:
 
                User.query().filter(User.active == True)\
 
                    .filter(User.username == value).one()
 
            except Exception:
 
                msg = M(self, 'invalid_username', state, username=value)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(username=msg)
 
                )
 

	
 
    return _validator
 

	
 

	
 
def ValidUsersGroup(edit=False, old_data={}):
 
def ValidUserGroup(edit=False, old_data={}):
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'invalid_group': _(u'Invalid user group name'),
 
            'group_exist': _(u'User group "%(usersgroup)s" already exists'),
 
            'invalid_usersgroup_name':
 
                _(u'user group name may only contain  alphanumeric '
 
            'group_exist': _(u'User group "%(usergroup)s" already exists'),
 
            'invalid_usergroup_name':
 
                _(u'user group name may only contain alphanumeric '
 
                  'characters underscores, periods or dashes and must begin '
 
                  'with alphanumeric character')
 
        }
 

	
 
        def validate_python(self, value, state):
 
            if value in ['default']:
 
                msg = M(self, 'invalid_group', state)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(users_group_name=msg)
 
                )
 
            #check if group is unique
 
            old_ugname = None
 
            if edit:
 
                old_id = old_data.get('users_group_id')
 
                old_ugname = UsersGroup.get(old_id).users_group_name
 
                old_ugname = UserGroup.get(old_id).users_group_name
 

	
 
            if old_ugname != value or not edit:
 
                is_existing_group = UsersGroup.get_by_group_name(value,
 
                is_existing_group = UserGroup.get_by_group_name(value,
 
                                                        case_insensitive=True)
 
                if is_existing_group:
 
                    msg = M(self, 'group_exist', state, usersgroup=value)
 
                    msg = M(self, 'group_exist', state, usergroup=value)
 
                    raise formencode.Invalid(msg, value, state,
 
                        error_dict=dict(users_group_name=msg)
 
                    )
 

	
 
            if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
 
                msg = M(self, 'invalid_usersgroup_name', state)
 
                msg = M(self, 'invalid_usergroup_name', state)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(users_group_name=msg)
 
                )
 

	
 
    return _validator
 

	
 

	
 
def ValidReposGroup(edit=False, old_data={}):
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'group_parent_id': _(u'Cannot assign this group as parent'),
 
            'group_exists': _(u'Group "%(group_name)s" already exists'),
 
            'repo_exists':
 
                _(u'Repository with name "%(group_name)s" already exists')
 
        }
 

	
 
        def validate_python(self, value, state):
 
            # TODO WRITE VALIDATIONS
 
            group_name = value.get('group_name')
 
            group_parent_id = value.get('group_parent_id')
 

	
 
            # slugify repo group just in case :)
 
            slug = repo_name_slug(group_name)
 

	
 
            # check for parent of self
 
            parent_of_self = lambda: (
 
                old_data['group_id'] == int(group_parent_id)
 
                if group_parent_id else False
 
            )
 
            if edit and parent_of_self():
 
                msg = M(self, 'group_parent_id', state)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(group_parent_id=msg)
 
                )
 

	
 
            old_gname = None
 
            if edit:
 
                old_gname = RepoGroup.get(old_data.get('group_id')).group_name
 

	
 
            if old_gname != group_name or not edit:
 

	
 
                # check group
 
                gr = RepoGroup.query()\
 
                      .filter(RepoGroup.group_name == slug)\
 
                      .filter(RepoGroup.group_parent_id == group_parent_id)\
 
                      .scalar()
 

	
 
                if gr:
 
                    msg = M(self, 'group_exists', state, group_name=slug)
 
                    raise formencode.Invalid(msg, value, state,
 
                            error_dict=dict(group_name=msg)
 
                    )
 

	
 
                # check for same repo
 
                repo = Repository.query()\
 
                      .filter(Repository.repo_name == slug)\
 
                      .scalar()
 

	
 
                if repo:
 
                    msg = M(self, 'repo_exists', state, group_name=slug)
 
                    raise formencode.Invalid(msg, value, state,
 
                            error_dict=dict(group_name=msg)
 
                    )
 

	
 
    return _validator
 

	
 

	
 
def ValidPassword():
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'invalid_password':
 
                _(u'Invalid characters (non-ascii) in password')
 
        }
 

	
 
        def validate_python(self, value, state):
 
            try:
 
                (value or '').decode('ascii')
 
            except UnicodeError:
 
                msg = M(self, 'invalid_password', state)
 
                raise formencode.Invalid(msg, value, state,)
 
    return _validator
 

	
 

	
 
def ValidPasswordsMatch():
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'password_mismatch': _(u'Passwords do not match'),
 
        }
 

	
 
        def validate_python(self, value, state):
 

	
 
            pass_val = value.get('password') or value.get('new_password')
 
            if pass_val != value['password_confirmation']:
 
                msg = M(self, 'password_mismatch', state)
 
                raise formencode.Invalid(msg, value, state,
 
                     error_dict=dict(password_confirmation=msg)
 
@@ -511,195 +511,195 @@ def CanCreateGroup(can_create_in_root=Fa
 
            'permission_denied': _(u"You don't have permissions "
 
                                   "to create a group in this location")
 
        }
 

	
 
        def to_python(self, value, state):
 
            #root location
 
            if value in [-1, "-1"]:
 
                return None
 
            return value
 

	
 
        def validate_python(self, value, state):
 
            gr = RepoGroup.get(value)
 
            gr_name = gr.group_name if gr else None  # None means ROOT location
 

	
 
            if can_create_in_root and gr is None:
 
                #we can create in root, we're fine no validations required
 
                return
 

	
 
            forbidden_in_root = gr is None and can_create_in_root is False
 
            val = HasReposGroupPermissionAny('group.admin')
 
            forbidden = not val(gr_name, 'can create group validator')
 
            if forbidden_in_root or forbidden:
 
                msg = M(self, 'permission_denied', state)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(group_parent_id=msg)
 
                )
 

	
 
    return _validator
 

	
 

	
 
def ValidPerms(type_='repo'):
 
    if type_ == 'group':
 
        EMPTY_PERM = 'group.none'
 
    elif type_ == 'repo':
 
        EMPTY_PERM = 'repository.none'
 

	
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'perm_new_member_name':
 
                _(u'This username or user group name is not valid')
 
        }
 

	
 
        def to_python(self, value, state):
 
            perms_update = OrderedSet()
 
            perms_new = OrderedSet()
 
            # build a list of permission to update and new permission to create
 

	
 
            #CLEAN OUT ORG VALUE FROM NEW MEMBERS, and group them using
 
            new_perms_group = defaultdict(dict)
 
            for k, v in value.copy().iteritems():
 
                if k.startswith('perm_new_member'):
 
                    del value[k]
 
                    _type, part = k.split('perm_new_member_')
 
                    args = part.split('_')
 
                    if len(args) == 1:
 
                        new_perms_group[args[0]]['perm'] = v
 
                    elif len(args) == 2:
 
                        _key, pos = args
 
                        new_perms_group[pos][_key] = v
 

	
 
            # fill new permissions in order of how they were added
 
            for k in sorted(map(int, new_perms_group.keys())):
 
                perm_dict = new_perms_group[str(k)]
 
                new_member = perm_dict.get('name')
 
                new_perm = perm_dict.get('perm')
 
                new_type = perm_dict.get('type')
 
                if new_member and new_perm and new_type:
 
                    perms_new.add((new_member, new_perm, new_type))
 

	
 
            for k, v in value.iteritems():
 
                if k.startswith('u_perm_') or k.startswith('g_perm_'):
 
                    member = k[7:]
 
                    t = {'u': 'user',
 
                         'g': 'users_group'
 
                    }[k[0]]
 
                    if member == 'default':
 
                        if value.get('repo_private'):
 
                            # set none for default when updating to
 
                            # private repo
 
                            v = EMPTY_PERM
 
                    perms_update.add((member, v, t))
 
            #always set NONE when private flag is set
 
            if value.get('repo_private'):
 
                perms_update.add(('default', EMPTY_PERM, 'user'))
 

	
 
            value['perms_updates'] = list(perms_update)
 
            value['perms_new'] = list(perms_new)
 

	
 
            # update permissions
 
            for k, v, t in perms_new:
 
                try:
 
                    if t is 'user':
 
                        self.user_db = User.query()\
 
                            .filter(User.active == True)\
 
                            .filter(User.username == k).one()
 
                    if t is 'users_group':
 
                        self.user_db = UsersGroup.query()\
 
                            .filter(UsersGroup.users_group_active == True)\
 
                            .filter(UsersGroup.users_group_name == k).one()
 
                        self.user_db = UserGroup.query()\
 
                            .filter(UserGroup.users_group_active == True)\
 
                            .filter(UserGroup.users_group_name == k).one()
 

	
 
                except Exception:
 
                    log.exception('Updated permission failed')
 
                    msg = M(self, 'perm_new_member_type', state)
 
                    raise formencode.Invalid(msg, value, state,
 
                        error_dict=dict(perm_new_member_name=msg)
 
                    )
 
            return value
 
    return _validator
 

	
 

	
 
def ValidSettings():
 
    class _validator(formencode.validators.FancyValidator):
 
        def _to_python(self, value, state):
 
            # settings  form for users that are not admin
 
            # can't edit certain parameters, it's extra backup if they mangle
 
            # with forms
 

	
 
            forbidden_params = [
 
                'user', 'repo_type', 'repo_enable_locking',
 
                'repo_enable_downloads', 'repo_enable_statistics'
 
            ]
 

	
 
            for param in forbidden_params:
 
                if param in value:
 
                    del value[param]
 
            return value
 

	
 
        def validate_python(self, value, state):
 
            pass
 
    return _validator
 

	
 

	
 
def ValidPath():
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'invalid_path': _(u'This is not a valid path')
 
        }
 

	
 
        def validate_python(self, value, state):
 
            if not os.path.isdir(value):
 
                msg = M(self, 'invalid_path', state)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(paths_root_path=msg)
 
                )
 
    return _validator
 

	
 

	
 
def UniqSystemEmail(old_data={}):
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'email_taken': _(u'This e-mail address is already taken')
 
        }
 

	
 
        def _to_python(self, value, state):
 
            return value.lower()
 

	
 
        def validate_python(self, value, state):
 
            if (old_data.get('email') or '').lower() != value:
 
                user = User.get_by_email(value, case_insensitive=True)
 
                if user:
 
                    msg = M(self, 'email_taken', state)
 
                    raise formencode.Invalid(msg, value, state,
 
                        error_dict=dict(email=msg)
 
                    )
 
    return _validator
 

	
 

	
 
def ValidSystemEmail():
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 
            'non_existing_email': _(u'e-mail "%(email)s" does not exist.')
 
        }
 

	
 
        def _to_python(self, value, state):
 
            return value.lower()
 

	
 
        def validate_python(self, value, state):
 
            user = User.get_by_email(value, case_insensitive=True)
 
            if user is None:
 
                msg = M(self, 'non_existing_email', state, email=value)
 
                raise formencode.Invalid(msg, value, state,
 
                    error_dict=dict(email=msg)
 
                )
 

	
 
    return _validator
 

	
 

	
 
def LdapLibValidator():
 
    class _validator(formencode.validators.FancyValidator):
 
        messages = {
 

	
 
        }
 

	
 
        def validate_python(self, value, state):
 
            try:
rhodecode/public/js/rhodecode.js
Show inline comments
 
@@ -1208,193 +1208,193 @@ var  getSelectionLink = function(e) {
 
	    // if we select more than 2 lines
 
	    if (ranges[0] != ranges[1]){
 
	        if(YUD.get('linktt') == null){
 
	            hl_div = document.createElement('div');
 
	            hl_div.id = 'linktt';
 
	        }
 
	        hl_div.innerHTML = '';
 

	
 
	        anchor = '#L'+ranges[0]+'-'+ranges[1];
 
	        var link = document.createElement('a');
 
	        link.href = location.href.substring(0,location.href.indexOf('#'))+anchor;
 
	        link.innerHTML = _TM['Selection link'];
 
	        hl_div.appendChild(link);
 
	        YUD.get('body').appendChild(hl_div);
 
	        
 
	        xy = YUD.getXY(till.id);
 

	
 
	        YUD.addClass('linktt', 'hl-tip-box');
 
	        YUD.setStyle('linktt','top',xy[1]+offset+'px');
 
	        YUD.setStyle('linktt','left',xy[0]+'px');
 
	        YUD.setStyle('linktt','visibility','visible');
 

	
 
	    }
 
	    else{
 
	    	YUD.setStyle('linktt','visibility','hidden');
 
	    }
 
	}
 
};
 

	
 
var deleteNotification = function(url, notification_id,callbacks){
 
    var callback = { 
 
		success:function(o){
 
		    var obj = YUD.get(String("notification_"+notification_id));
 
		    if(obj.parentNode !== undefined){
 
				obj.parentNode.removeChild(obj);
 
			}
 
			_run_callbacks(callbacks);
 
		},
 
	    failure:function(o){
 
	        alert("error");
 
	    },
 
	};
 
    var postData = '_method=delete';
 
    var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
 
    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, 
 
    											  callback, postData);
 
};	
 

	
 
var readNotification = function(url, notification_id,callbacks){
 
    var callback = { 
 
		success:function(o){
 
		    var obj = YUD.get(String("notification_"+notification_id));
 
		    YUD.removeClass(obj, 'unread');
 
		    var r_button = YUD.getElementsByClassName('read-notification',null,obj.children[0])[0];
 
		    
 
		    if(r_button.parentNode !== undefined){
 
		    	r_button.parentNode.removeChild(r_button);
 
			}		    
 
			_run_callbacks(callbacks);
 
		},
 
	    failure:function(o){
 
	        alert("error");
 
	    },
 
	};
 
    var postData = '_method=put';
 
    var sUrl = url.replace('__NOTIFICATION_ID__',notification_id);
 
    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, 
 
    											  callback, postData);
 
};	
 

	
 
/** MEMBERS AUTOCOMPLETE WIDGET **/
 

	
 
var MembersAutoComplete = function (divid, cont, users_list, groups_list) {
 
    var myUsers = users_list;
 
    var myGroups = groups_list;
 

	
 
    // Define a custom search function for the DataSource of users
 
    var matchUsers = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myUsers.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                contact = myUsers[i];
 
                if (((contact.fname+"").toLowerCase().indexOf(query) > -1) || 
 
                   	 ((contact.lname+"").toLowerCase().indexOf(query) > -1) || 
 
                   	 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
 
                       matches[matches.length] = contact;
 
                   }
 
            }
 
            return matches;
 
        };
 

	
 
    // Define a custom search function for the DataSource of usersGroups
 
    // Define a custom search function for the DataSource of userGroups
 
    var matchGroups = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myGroups.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                matched_group = myGroups[i];
 
                if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
 
                    matches[matches.length] = matched_group;
 
                }
 
            }
 
            return matches;
 
        };
 

	
 
    //match all
 
    var matchAll = function (sQuery) {
 
            u = matchUsers(sQuery);
 
            g = matchGroups(sQuery);
 
            return u.concat(g);
 
        };
 

	
 
    // DataScheme for members
 
    var memberDS = new YAHOO.util.FunctionDataSource(matchAll);
 
    memberDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "grname", "grmembers", "gravatar_lnk"]
 
    };
 

	
 
    // DataScheme for owner
 
    var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
 
    ownerDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
 
    };
 

	
 
    // Instantiate AutoComplete for perms
 
    var membersAC = new YAHOO.widget.AutoComplete(divid, cont, memberDS);
 
    membersAC.useShadow = false;
 
    membersAC.resultTypeList = false;
 
    membersAC.animVert = false;
 
    membersAC.animHoriz = false;    
 
    membersAC.animSpeed = 0.1;
 

	
 
    // Instantiate AutoComplete for owner
 
    var ownerAC = new YAHOO.widget.AutoComplete("user", "owner_container", ownerDS);
 
    ownerAC.useShadow = false;
 
    ownerAC.resultTypeList = false;
 
    ownerAC.animVert = false;
 
    ownerAC.animHoriz = false;
 
    ownerAC.animSpeed = 0.1;
 

	
 
    // Helper highlight function for the formatter
 
    var highlightMatch = function (full, snippet, matchindex) {
 
            return full.substring(0, matchindex) 
 
            + "<span class='match'>" 
 
            + full.substr(matchindex, snippet.length) 
 
            + "</span>" + full.substring(matchindex + snippet.length);
 
        };
 

	
 
    // Custom formatter to highlight the matching letters
 
    var custom_formatter = function (oResultData, sQuery, sResultMatch) {
 
            var query = sQuery.toLowerCase();
 
            var _gravatar = function(res, em, group){
 
            	if (group !== undefined){
 
            		em = '/images/icons/group.png'
 
            	}
 
            	tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
 
            	return tmpl.format(em,res)
 
            }
 
            // group
 
            if (oResultData.grname != undefined) {
 
                var grname = oResultData.grname;
 
                var grmembers = oResultData.grmembers;
 
                var grnameMatchIndex = grname.toLowerCase().indexOf(query);
 
                var grprefix = "{0}: ".format(_TM['Group']);
 
                var grsuffix = " (" + grmembers + "  )";
 
                var grsuffix = " ({0}  {1})".format(grmembers, _TM['members']);
 

	
 
                if (grnameMatchIndex > -1) {
 
                    return _gravatar(grprefix + highlightMatch(grname, query, grnameMatchIndex) + grsuffix,null,true);
 
                }
 
			    return _gravatar(grprefix + oResultData.grname + grsuffix, null,true);
 
            // Users
 
            } else if (oResultData.nname != undefined) {
 
                var fname = oResultData.fname || "";
 
                var lname = oResultData.lname || "";
 
                var nname = oResultData.nname;
 
                
 
                // Guard against null value
 
                var fnameMatchIndex = fname.toLowerCase().indexOf(query),
 
                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
 
                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
 
                    displayfname, displaylname, displaynname;
 

	
 
                if (fnameMatchIndex > -1) {
 
@@ -1626,193 +1626,193 @@ var MentionsAutoComplete = function (div
 
			var ac_obj = args[0];
 
			var currentMessage = args[1];
 
			var currentCaretPosition = args[0]._elTextbox.selectionStart;
 
	
 
			var unam = ownerAC.get_mention(currentMessage, currentCaretPosition); 
 
			var curr_search = null;
 
			if(unam[0]){
 
				curr_search = unam[0];
 
			}
 
			
 
			ownerAC.dataSource.chunks = unam[1];
 
			ownerAC.dataSource.mentionQuery = curr_search;
 
	
 
		})
 
	}	
 
    return {
 
        ownerDS: ownerDS,
 
        ownerAC: ownerAC,
 
    };
 
}
 

	
 
var addReviewMember = function(id,fname,lname,nname,gravatar_link){
 
	var members  = YUD.get('review_members');
 
	var tmpl = '<li id="reviewer_{2}">'+
 
    '<div class="reviewers_member">'+
 
      '<div class="gravatar"><img alt="gravatar" src="{0}"/> </div>'+
 
      '<div style="float:left">{1}</div>'+
 
      '<input type="hidden" value="{2}" name="review_members" />'+
 
      '<span class="delete_icon action_button" onclick="removeReviewMember({2})"></span>'+
 
    '</div>'+
 
    '</li>'	;
 
    var displayname = "{0} {1} ({2})".format(fname,lname,nname);
 
	var element = tmpl.format(gravatar_link,displayname,id);
 
	// check if we don't have this ID already in
 
	var ids = [];
 
	var _els = YUQ('#review_members li');
 
	for (el in _els){
 
		ids.push(_els[el].id)
 
	}
 
	if(ids.indexOf('reviewer_'+id) == -1){
 
		//only add if it's not there
 
		members.innerHTML += element;
 
	}
 
	    
 
}
 

	
 
var removeReviewMember = function(reviewer_id, repo_name, pull_request_id){
 
	var el = YUD.get('reviewer_{0}'.format(reviewer_id));
 
	if (el.parentNode !== undefined){
 
		el.parentNode.removeChild(el);
 
	}
 
}
 

	
 
var updateReviewers = function(reviewers_ids, repo_name, pull_request_id){
 
	if (reviewers_ids === undefined){
 
  	  var reviewers_ids = [];
 
	  var ids = YUQ('#review_members input');
 
	  for(var i=0; i<ids.length;i++){
 
		  var id = ids[i].value
 
		  reviewers_ids.push(id);
 
	  }		
 
	}
 
	var url = pyroutes.url('pullrequest_update', {"repo_name":repo_name,
 
												  "pull_request_id": pull_request_id});
 
	var postData = {'_method':'put',
 
			        'reviewers_ids': reviewers_ids};
 
	var success = function(o){
 
		window.location.reload();
 
	}
 
	ajaxPOST(url,postData,success);
 
}
 

	
 
var PullRequestAutoComplete = function (divid, cont, users_list, groups_list) {
 
    var myUsers = users_list;
 
    var myGroups = groups_list;
 

	
 
    // Define a custom search function for the DataSource of users
 
    var matchUsers = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myUsers.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                contact = myUsers[i];
 
                if (((contact.fname+"").toLowerCase().indexOf(query) > -1) || 
 
                   	 ((contact.lname+"").toLowerCase().indexOf(query) > -1) || 
 
                   	 ((contact.nname) && ((contact.nname).toLowerCase().indexOf(query) > -1))) {
 
                       matches[matches.length] = contact;
 
                   }
 
            }
 
            return matches;
 
        };
 

	
 
    // Define a custom search function for the DataSource of usersGroups
 
    // Define a custom search function for the DataSource of userGroups
 
    var matchGroups = function (sQuery) {
 
            // Case insensitive matching
 
            var query = sQuery.toLowerCase();
 
            var i = 0;
 
            var l = myGroups.length;
 
            var matches = [];
 

	
 
            // Match against each name of each contact
 
            for (; i < l; i++) {
 
                matched_group = myGroups[i];
 
                if (matched_group.grname.toLowerCase().indexOf(query) > -1) {
 
                    matches[matches.length] = matched_group;
 
                }
 
            }
 
            return matches;
 
        };
 

	
 
    //match all
 
    var matchAll = function (sQuery) {
 
            u = matchUsers(sQuery);
 
            return u
 
        };
 

	
 
    // DataScheme for owner
 
    var ownerDS = new YAHOO.util.FunctionDataSource(matchUsers);
 

	
 
    ownerDS.responseSchema = {
 
        fields: ["id", "fname", "lname", "nname", "gravatar_lnk"]
 
    };
 

	
 
    // Instantiate AutoComplete for mentions
 
    var reviewerAC = new YAHOO.widget.AutoComplete(divid, cont, ownerDS);
 
    reviewerAC.useShadow = false;
 
    reviewerAC.resultTypeList = false;
 
    reviewerAC.suppressInputUpdate = true;
 
    reviewerAC.animVert = false;
 
    reviewerAC.animHoriz = false;    
 
    reviewerAC.animSpeed = 0.1;
 
    
 
    // Helper highlight function for the formatter
 
    var highlightMatch = function (full, snippet, matchindex) {
 
            return full.substring(0, matchindex) 
 
            + "<span class='match'>" 
 
            + full.substr(matchindex, snippet.length) 
 
            + "</span>" + full.substring(matchindex + snippet.length);
 
        };
 

	
 
    // Custom formatter to highlight the matching letters
 
    reviewerAC.formatResult = function (oResultData, sQuery, sResultMatch) {
 
		    var org_sQuery = sQuery;
 
		    if(this.dataSource.mentionQuery != null){
 
		    	sQuery = this.dataSource.mentionQuery;		    	
 
		    }
 

	
 
            var query = sQuery.toLowerCase();
 
            var _gravatar = function(res, em, group){
 
            	if (group !== undefined){
 
            		em = '/images/icons/group.png'
 
            	}
 
            	tmpl = '<div class="ac-container-wrap"><img class="perm-gravatar-ac" src="{0}"/>{1}</div>'
 
            	return tmpl.format(em,res)
 
            }
 
            if (oResultData.nname != undefined) {
 
                var fname = oResultData.fname || "";
 
                var lname = oResultData.lname || "";
 
                var nname = oResultData.nname;
 
                
 
                // Guard against null value
 
                var fnameMatchIndex = fname.toLowerCase().indexOf(query),
 
                    lnameMatchIndex = lname.toLowerCase().indexOf(query),
 
                    nnameMatchIndex = nname.toLowerCase().indexOf(query),
 
                    displayfname, displaylname, displaynname;
 

	
 
                if (fnameMatchIndex > -1) {
 
                    displayfname = highlightMatch(fname, query, fnameMatchIndex);
 
                } else {
 
                    displayfname = fname;
 
                }
 

	
 
                if (lnameMatchIndex > -1) {
 
                    displaylname = highlightMatch(lname, query, lnameMatchIndex);
 
                } else {
 
                    displaylname = lname;
 
                }
 

	
 
                if (nnameMatchIndex > -1) {
 
                    displaynname = "(" + highlightMatch(nname, query, nnameMatchIndex) + ")";
 
                } else {
 
                    displaynname = nname ? "(" + nname + ")" : "";
 
                }
 

	
 
                return _gravatar(displayfname + " " + displaylname + " " + displaynname, oResultData.gravatar_lnk);
 
            } else {
 
                return '';
 
            }
 
        };
rhodecode/templates/admin/repos/repo_edit_perms.html
Show inline comments
 
<table id="permissions_manage" class="noborder">
 
    <tr>
 
        <td>${_('none')}</td>
 
        <td>${_('read')}</td>
 
        <td>${_('write')}</td>
 
        <td>${_('admin')}</td>
 
        <td>${_('member')}</td>
 
        <td></td>
 
    </tr>
 
    ## USERS
 
    %for r2p in c.repo_info.repo_to_perm:
 
        %if r2p.user.username =='default' and c.repo_info.private:
 
            <tr>
 
                <td colspan="4">
 
                    <span class="private_repo_msg">
 
                    ${_('private repository')}
 
                    </span>
 
                </td>
 
                <td class="private_repo_msg"><img style="vertical-align:bottom" src="${h.url('/images/icons/user.png')}"/>${_('default')}</td>
 
            </tr>
 
        %else:
 
        <tr id="id${id(r2p.user.username)}">
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.none')}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.read')}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.write')}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'repository.admin')}</td>
 
            <td style="white-space: nowrap;">
 
                <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
            </td>
 
            <td>
 
              %if r2p.user.username !='default':
 
                <span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
 
                ${_('revoke')}
 
                </span>
 
              %endif
 
            </td>
 
        </tr>
 
        %endif
 
    %endfor
 

	
 
    ## USER GROUPS
 
    %for g2p in c.repo_info.users_group_to_perm:
 
        <tr id="id${id(g2p.users_group.users_group_name)}">
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.none')}</td>
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.read')}</td>
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.write')}</td>
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.admin')}</td>
 
            <td style="white-space: nowrap;">
 
                <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>
 
                %if h.HasPermissionAny('hg.admin')():
 
                 <a href="${h.url('edit_users_group',id=g2p.users_group.users_group_id)}">${g2p.users_group.users_group_name}</a>
 
                %else:
 
                 ${g2p.users_group.users_group_name}
 
                %endif
 
            </td>
 
            <td>
 
                <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
 
                <span class="delete_icon action_button" onclick="ajaxActionUserGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
 
                ${_('revoke')}
 
                </span>
 
            </td>
 
        </tr>
 
    %endfor
 
    <%
 
    _tmpl = h.literal("""' \
 
        <td><input type="radio" value="repository.none" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td><input type="radio" value="repository.read" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td><input type="radio" value="repository.write" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td><input type="radio" value="repository.admin" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td class="ac"> \
 
            <div class="perm_ac" id="perm_ac_{0}"> \
 
                <input class="yui-ac-input" id="perm_new_member_name_{0}" name="perm_new_member_name_{0}" value="" type="text"> \
 
                <input id="perm_new_member_type_{0}" name="perm_new_member_type_{0}" value="" type="hidden">  \
 
                <div id="perm_container_{0}"></div> \
 
            </div> \
 
        </td> \
 
        <td></td>'""")
 
    %>
 
    ## ADD HERE DYNAMICALLY NEW INPUTS FROM THE '_tmpl'
 
    <tr class="new_members last_new_member" id="add_perm_input"></tr>
 
    <tr>
 
        <td colspan="6">
 
            <span id="add_perm" class="add_icon" style="cursor: pointer;">
 
            ${_('Add another member')}
 
            </span>
 
        </td>
 
    </tr>
 
</table>
 
<script type="text/javascript">
 
function ajaxActionUser(user_id, field_id) {
 
    var sUrl = "${h.url('delete_repo_user',repo_name=c.repo_name)}";
 
    var callback = {
 
        success: function (o) {
 
            var tr = YUD.get(String(field_id));
 
            tr.parentNode.removeChild(tr);
 
        },
 
        failure: function (o) {
 
            alert("${_('Failed to remove user')}");
 
        },
 
    };
 
    var postData = '_method=delete&user_id=' + user_id;
 
    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
 
};
 

	
 
function ajaxActionUsersGroup(users_group_id,field_id){
 
function ajaxActionUserGroup(users_group_id,field_id){
 
    var sUrl = "${h.url('delete_repo_users_group',repo_name=c.repo_name)}";
 
    var callback = {
 
        success:function(o){
 
            var tr = YUD.get(String(field_id));
 
            tr.parentNode.removeChild(tr);
 
        },
 
        failure:function(o){
 
            alert("${_('Failed to remove user group')}");
 
        },
 
    };
 
    var postData = '_method=delete&users_group_id='+users_group_id;
 
    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
 
};
 

	
 
YUE.onDOMReady(function () {
 
    if (!YUD.hasClass('perm_new_member_name', 'error')) {
 
        YUD.setStyle('add_perm_input', 'display', 'none');
 
    }
 
    YAHOO.util.Event.addListener('add_perm', 'click', function () {
 
        addPermAction(${_tmpl}, ${c.users_array|n}, ${c.users_groups_array|n});
 
    });
 
});
 

	
 
</script>
rhodecode/templates/admin/repos_groups/repos_group_edit_perms.html
Show inline comments
 
<table id="permissions_manage" class="noborder">
 
    <tr>
 
        <td>${_('none')}</td>
 
        <td>${_('read')}</td>
 
        <td>${_('write')}</td>
 
        <td>${_('admin')}</td>
 
        <td>${_('member')}</td>
 
        <td></td>
 
    </tr>
 
    ## USERS
 
    %for r2p in c.repos_group.repo_group_to_perm:
 
        ##forbid revoking permission from yourself
 
        <tr id="id${id(r2p.user.username)}">
 
            %if c.rhodecode_user.user_id != r2p.user.user_id or c.rhodecode_user.is_admin:
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none')}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read')}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write')}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin')}</td>
 
            <td style="white-space: nowrap;">
 
                <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
            </td>
 
            <td>
 
              %if r2p.user.username !='default':
 
                <span class="delete_icon action_button" onclick="ajaxActionUser(${r2p.user.user_id},'${'id%s'%id(r2p.user.username)}')">
 
                ${_('revoke')}
 
                </span>
 
              %endif
 
            </td>
 
            %else:
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.none', disabled="disabled")}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.read', disabled="disabled")}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.write', disabled="disabled")}</td>
 
            <td>${h.radio('u_perm_%s' % r2p.user.username,'group.admin', disabled="disabled")}</td>
 
            <td style="white-space: nowrap;">
 
                <img class="perm-gravatar" src="${h.gravatar_url(r2p.user.email,14)}"/>${r2p.user.username if r2p.user.username != 'default' else _('default')}
 
            </td>
 
            <td>
 
            </td>
 
            %endif
 
        </tr>
 
    %endfor
 

	
 
    ## USER GROUPS
 
    %for g2p in c.repos_group.users_group_to_perm:
 
        <tr id="id${id(g2p.users_group.users_group_name)}">
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.none')}</td>
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.read')}</td>
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.write')}</td>
 
            <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'group.admin')}</td>
 
            <td style="white-space: nowrap;">
 
                <img class="perm-gravatar" src="${h.url('/images/icons/group.png')}"/>${g2p.users_group.users_group_name}
 
            </td>
 
            <td>
 
                <span class="delete_icon action_button" onclick="ajaxActionUsersGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
 
                <span class="delete_icon action_button" onclick="ajaxActionUserGroup(${g2p.users_group.users_group_id},'${'id%s'%id(g2p.users_group.users_group_name)}')">
 
                ${_('revoke')}
 
                </span>
 
            </td>
 
        </tr>
 
    %endfor
 
<%
 
    _tmpl = h.literal("""' \
 
        <td><input type="radio" value="group.none" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td><input type="radio" value="group.read" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td><input type="radio" value="group.write" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td><input type="radio" value="group.admin" name="perm_new_member_{0}" id="perm_new_member_{0}"></td> \
 
        <td class="ac"> \
 
            <div class="perm_ac" id="perm_ac_{0}"> \
 
                <input class="yui-ac-input" id="perm_new_member_name_{0}" name="perm_new_member_name_{0}" value="" type="text"> \
 
                <input id="perm_new_member_type_{0}" name="perm_new_member_type_{0}" value="" type="hidden">  \
 
                <div id="perm_container_{0}"></div> \
 
            </div> \
 
        </td> \
 
        <td></td>'""")
 
    %>
 
    ## ADD HERE DYNAMICALLY NEW INPUTS FROM THE '_tmpl'
 
    <tr class="new_members last_new_member" id="add_perm_input"></tr>
 
    <tr>
 
        <td colspan="6">
 
            <span id="add_perm" class="add_icon" style="cursor: pointer;">
 
            ${_('Add another member')}
 
            </span>
 
        </td>
 
    </tr>
 
    <tr>
 
        <td colspan="6">
 
           ${h.checkbox('recursive',value="True", label=_('apply to children'))}
 
           <span class="help-block">${_('Set or revoke permission to all children of that group, including non-private repositories and other groups')}</span>
 
        </td>
 
    </tr>
 
</table>
 
<script type="text/javascript">
 
function ajaxActionUser(user_id, field_id) {
 
    var sUrl = "${h.url('delete_repos_group_user_perm',group_name=c.repos_group.group_name)}";
 
    var callback = {
 
        success: function (o) {
 
            var tr = YUD.get(String(field_id));
 
            tr.parentNode.removeChild(tr);
 
        },
 
        failure: function (o) {
 
            alert("${_('Failed to remove user')}");
 
        },
 
    };
 
    var recursive = YUD.get('recursive').checked;
 
    var postData = '_method=delete&recursive={0}&user_id={1}'.format(recursive,user_id);
 
    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
 
};
 

	
 
function ajaxActionUsersGroup(users_group_id,field_id){
 
function ajaxActionUserGroup(users_group_id,field_id){
 
    var sUrl = "${h.url('delete_repos_group_users_group_perm',group_name=c.repos_group.group_name)}";
 
    var callback = {
 
        success:function(o){
 
            var tr = YUD.get(String(field_id));
 
            tr.parentNode.removeChild(tr);
 
        },
 
        failure:function(o){
 
            alert("${_('Failed to remove user group')}");
 
        },
 
    };
 
    var recursive = YUD.get('recursive').checked;
 
    var postData = '_method=delete&recursive={0}&users_group_id={1}'.format(recursive,users_group_id);
 
    var request = YAHOO.util.Connect.asyncRequest('POST', sUrl, callback, postData);
 
};
 

	
 
YUE.onDOMReady(function () {
 
    if (!YUD.hasClass('perm_new_member_name', 'error')) {
 
        YUD.setStyle('add_perm_input', 'display', 'none');
 
    }
 
    YAHOO.util.Event.addListener('add_perm', 'click', function () {
 
        addPermAction(${_tmpl}, ${c.users_array|n}, ${c.users_groups_array|n});
 
    });
 
});
 

	
 
</script>
rhodecode/templates/admin/users_groups/users_group_edit.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Edit user group')} ${c.users_group.users_group_name} - ${c.rhodecode_name}
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    ${h.link_to(_('Admin'),h.url('admin_home'))}
 
    &raquo;
 
    ${h.link_to(_('UsersGroups'),h.url('users_groups'))}
 
    ${h.link_to(_('UserGroups'),h.url('users_groups'))}
 
    &raquo;
 
    ${_('edit')} "${c.users_group.users_group_name}"
 
</%def>
 

	
 
<%def name="page_nav()">
 
    ${self.menu('admin')}
 
</%def>
 

	
 
<%def name="main()">
 
<div class="box box-left">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <!-- end box / title -->
 
    ${h.form(url('users_group', id=c.users_group.users_group_id),method='put', id='edit_users_group')}
 
    <div class="form">
 
        <!-- fields -->
 
            <div class="fields">
 
                 <div class="field">
 
                    <div class="label">
 
                        <label for="users_group_name">${_('Group name')}:</label>
 
                    </div>
 
                    <div class="input">
 
                        ${h.text('users_group_name',class_='small')}
 
                    </div>
 
                 </div>
 

	
 
                 <div class="field">
 
                    <div class="label label-checkbox">
 
                        <label for="users_group_active">${_('Active')}:</label>
 
                    </div>
 
                    <div class="checkboxes">
 
                        ${h.checkbox('users_group_active',value=True)}
 
                    </div>
 
                 </div>
 
                <div class="field">
 
                    <div class="label">
 
                        <label for="users_group_active">${_('Members')}:</label>
 
                    </div>
 
                    <div class="select">
 
                        <table>
 
                                <tr>
 
                                    <td>
 
                                        <div>
 
                                            <div style="float:left">
 
                                                <div class="text" style="padding: 0px 0px 6px;">${_('Choosen group members')}</div>
 
                                                ${h.select('users_group_members',[x[0] for x in c.group_members],c.group_members,multiple=True,size=8,style="min-width:210px")}
 
                                               <div  id="remove_all_elements" style="cursor:pointer;text-align:center">
 
                                                   ${_('Remove all elements')}
 
                                                   <img alt="remove" style="vertical-align:text-bottom" src="${h.url('/images/icons/arrow_right.png')}"/>
 
                                               </div>
 
                                            </div>
 
                                            <div style="float:left;width:20px;padding-top:50px">
 
                                                <img alt="add" id="add_element"
 
                                                    style="padding:2px;cursor:pointer"
 
                                                    src="${h.url('/images/icons/arrow_left.png')}"/>
 
                                                <br />
 
                                                <img alt="remove" id="remove_element"
 
                                                    style="padding:2px;cursor:pointer"
 
                                                    src="${h.url('/images/icons/arrow_right.png')}"/>
 
                                            </div>
 
                                            <div style="float:left">
 
                                                 <div class="text" style="padding: 0px 0px 6px;">${_('Available members')}</div>
 
                                                 ${h.select('available_members',[],c.available_members,multiple=True,size=8,style="min-width:210px")}
 
                                                 <div id="add_all_elements" style="cursor:pointer;text-align:center">
 
                                                       <img alt="add" style="vertical-align:text-bottom" src="${h.url('/images/icons/arrow_left.png')}"/>
 
                                                        ${_('Add all elements')}
 
                                                 </div>
 
                                            </div>
 
                                        </div>
 
                                    </td>
 
                                </tr>
 
                        </table>
 
                    </div>
 

	
 
                </div>
 
                <div class="buttons">
 
                  ${h.submit('save',_('save'),class_="ui-btn large")}
 
                </div>
 
            </div>
 
    </div>
 
${h.end_form()}
 
</div>
 

	
 
<div class="box box-right">
 
    <!-- box / title -->
 
    <div class="title">
 
        <h5>${_('Permissions')}</h5>
 
    </div>
 
    ${h.form(url('users_group_perm', id=c.users_group.users_group_id), method='put')}
 
    <div class="form">
 
        <!-- fields -->
 
        <div class="fields">
 
             <div class="field">
 
                <div class="label label-checkbox">
rhodecode/tests/api/api_base.py
Show inline comments
 
from __future__ import with_statement
 
import random
 
import mock
 

	
 
from rhodecode.tests import *
 
from rhodecode.lib.compat import json
 
from rhodecode.lib.auth import AuthUser
 
from rhodecode.model.user import UserModel
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.meta import Session
 
from rhodecode.model.scm import ScmModel
 
from rhodecode.model.db import Repository
 

	
 
API_URL = '/_admin/api'
 

	
 

	
 
def _build_data(apikey, method, **kw):
 
    """
 
    Builds API data with given random ID
 

	
 
    :param random_id:
 
    :type random_id:
 
    """
 
    random_id = random.randrange(1, 9999)
 
    return random_id, json.dumps({
 
        "id": random_id,
 
        "api_key": apikey,
 
        "method": method,
 
        "args": kw
 
    })
 

	
 
jsonify = lambda obj: json.loads(json.dumps(obj))
 

	
 

	
 
def crash(*args, **kwargs):
 
    raise Exception('Total Crash !')
 

	
 

	
 
def api_call(test_obj, params):
 
    response = test_obj.app.post(API_URL, content_type='application/json',
 
                                 params=params)
 
    return response
 

	
 

	
 
TEST_USERS_GROUP = 'test_users_group'
 
TEST_USER_GROUP = 'test_users_group'
 

	
 

	
 
def make_users_group(name=TEST_USERS_GROUP):
 
    gr = UsersGroupModel().create(name=name)
 
    UsersGroupModel().add_user_to_group(users_group=gr,
 
def make_users_group(name=TEST_USER_GROUP):
 
    gr = UserGroupModel().create(name=name)
 
    UserGroupModel().add_user_to_group(users_group=gr,
 
                                        user=TEST_USER_ADMIN_LOGIN)
 
    Session().commit()
 
    return gr
 

	
 

	
 
def destroy_users_group(name=TEST_USERS_GROUP):
 
    UsersGroupModel().delete(users_group=name, force=True)
 
def destroy_users_group(name=TEST_USER_GROUP):
 
    UserGroupModel().delete(users_group=name, force=True)
 
    Session().commit()
 

	
 

	
 
def create_repo(repo_name, repo_type, owner=None):
 
    # create new repo
 
    form_data = _get_repo_create_params(
 
                    repo_name_full=repo_name,
 
                    repo_description='description %s' % repo_name,
 
                )
 
    cur_user = UserModel().get_by_username(owner or TEST_USER_ADMIN_LOGIN)
 
    r = RepoModel().create(form_data, cur_user)
 
    Session().commit()
 
    return r
 

	
 

	
 
def create_fork(fork_name, fork_type, fork_of):
 
    fork = RepoModel(Session())._get_repo(fork_of)
 
    r = create_repo(fork_name, fork_type)
 
    r.fork = fork
 
    Session().add(r)
 
    Session().commit()
 
    return r
 

	
 

	
 
def destroy_repo(repo_name):
 
    RepoModel().delete(repo_name)
 
    Session().commit()
 

	
 

	
 
class BaseTestApi(object):
 
    REPO = None
 
    REPO_TYPE = None
 

	
 
    @classmethod
 
    def setUpClass(self):
 
        self.usr = UserModel().get_by_username(TEST_USER_ADMIN_LOGIN)
 
        self.apikey = self.usr.api_key
 
        self.test_user = UserModel().create_or_update(
 
            username='test-api',
 
            password='test',
 
            email='test@api.rhodecode.org',
 
            firstname='first',
 
            lastname='last'
 
        )
 
        Session().commit()
 
        self.TEST_USER_LOGIN = self.test_user.username
 
        self.apikey_regular = self.test_user.api_key
 

	
 
    @classmethod
 
    def teardownClass(self):
 
        pass
 

	
 
    def setUp(self):
 
        self.maxDiff = None
 
        make_users_group()
 

	
 
    def tearDown(self):
 
        destroy_users_group()
 

	
 
    def _compare_ok(self, id_, expected, given):
 
        expected = jsonify({
 
            'id': id_,
 
            'error': None,
 
            'result': expected
 
        })
 
        given = json.loads(given)
 
        self.assertEqual(expected, given)
 

	
 
    def _compare_error(self, id_, expected, given):
 
        expected = jsonify({
 
            'id': id_,
 
            'error': expected,
 
            'result': None
 
        })
 
        given = json.loads(given)
 
        self.assertEqual(expected, given)
 

	
 
#    def test_Optional(self):
 
#        from rhodecode.controllers.api.api import Optional
 
#        option1 = Optional(None)
 
#        self.assertEqual('<Optional:%s>' % None, repr(option1))
 
#
 
#        self.assertEqual(1, Optional.extract(Optional(1)))
 
#        self.assertEqual('trololo', Optional.extract('trololo'))
 

	
 
    def test_api_wrong_key(self):
 
        id_, params = _build_data('trololo', 'get_user')
 
        response = api_call(self, params)
 

	
 
        expected = 'Invalid API KEY'
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    def test_api_missing_non_optional_param(self):
 
        id_, params = _build_data(self.apikey, 'get_repo')
 
        response = api_call(self, params)
 

	
 
@@ -906,389 +906,389 @@ class BaseTestApi(object):
 

	
 
        ret = {
 
            'msg': 'Created fork of `%s` as `%s`' % (self.REPO,
 
                                                     fork_name),
 
            'success': True
 
        }
 
        expected = ret
 
        self._compare_ok(id_, expected, given=response.body)
 
        destroy_repo(fork_name)
 

	
 
    def test_api_fork_repo_non_admin_specify_owner(self):
 
        fork_name = 'api-repo-fork'
 
        id_, params = _build_data(self.apikey_regular, 'fork_repo',
 
                                    repoid=self.REPO,
 
                                    fork_name=fork_name,
 
                                    owner=TEST_USER_ADMIN_LOGIN,
 
                                  )
 
        response = api_call(self, params)
 
        expected = 'Only RhodeCode admin can specify `owner` param'
 
        self._compare_error(id_, expected, given=response.body)
 
        destroy_repo(fork_name)
 

	
 
    def test_api_fork_repo_non_admin_no_permission_to_fork(self):
 
        RepoModel().grant_user_permission(repo=self.REPO,
 
                                          user=self.TEST_USER_LOGIN,
 
                                          perm='repository.none')
 
        fork_name = 'api-repo-fork'
 
        id_, params = _build_data(self.apikey_regular, 'fork_repo',
 
                                    repoid=self.REPO,
 
                                    fork_name=fork_name,
 
                                  )
 
        response = api_call(self, params)
 
        expected = 'repository `%s` does not exist' % (self.REPO)
 
        self._compare_error(id_, expected, given=response.body)
 
        destroy_repo(fork_name)
 

	
 
    def test_api_fork_repo_unknown_owner(self):
 
        fork_name = 'api-repo-fork'
 
        owner = 'i-dont-exist'
 
        id_, params = _build_data(self.apikey, 'fork_repo',
 
                                    repoid=self.REPO,
 
                                    fork_name=fork_name,
 
                                    owner=owner,
 
                                  )
 
        response = api_call(self, params)
 
        expected = 'user `%s` does not exist' % owner
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    def test_api_fork_repo_fork_exists(self):
 
        fork_name = 'api-repo-fork'
 
        create_fork(fork_name, self.REPO_TYPE, self.REPO)
 

	
 
        try:
 
            fork_name = 'api-repo-fork'
 

	
 
            id_, params = _build_data(self.apikey, 'fork_repo',
 
                                        repoid=self.REPO,
 
                                        fork_name=fork_name,
 
                                        owner=TEST_USER_ADMIN_LOGIN,
 
                                      )
 
            response = api_call(self, params)
 

	
 
            expected = "fork `%s` already exist" % fork_name
 
            self._compare_error(id_, expected, given=response.body)
 
        finally:
 
            destroy_repo(fork_name)
 

	
 
    def test_api_fork_repo_repo_exists(self):
 
        fork_name = self.REPO
 

	
 
        id_, params = _build_data(self.apikey, 'fork_repo',
 
                                    repoid=self.REPO,
 
                                    fork_name=fork_name,
 
                                    owner=TEST_USER_ADMIN_LOGIN,
 
                                  )
 
        response = api_call(self, params)
 

	
 
        expected = "repo `%s` already exist" % fork_name
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(RepoModel, 'create_fork', crash)
 
    def test_api_fork_repo_exception_occurred(self):
 
        fork_name = 'api-repo-fork'
 
        id_, params = _build_data(self.apikey, 'fork_repo',
 
                                    repoid=self.REPO,
 
                                    fork_name=fork_name,
 
                                    owner=TEST_USER_ADMIN_LOGIN,
 
                                  )
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to fork repository `%s` as `%s`' % (self.REPO,
 
                                                               fork_name)
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    def test_api_get_users_group(self):
 
        id_, params = _build_data(self.apikey, 'get_users_group',
 
                                  usersgroupid=TEST_USERS_GROUP)
 
                                  usersgroupid=TEST_USER_GROUP)
 
        response = api_call(self, params)
 

	
 
        users_group = UsersGroupModel().get_group(TEST_USERS_GROUP)
 
        users_group = UserGroupModel().get_group(TEST_USER_GROUP)
 
        members = []
 
        for user in users_group.members:
 
            user = user.user
 
            members.append(user.get_api_data())
 

	
 
        ret = users_group.get_api_data()
 
        ret['members'] = members
 
        expected = ret
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
    def test_api_get_users_groups(self):
 

	
 
        make_users_group('test_users_group2')
 

	
 
        id_, params = _build_data(self.apikey, 'get_users_groups',)
 
        response = api_call(self, params)
 

	
 
        expected = []
 
        for gr_name in [TEST_USERS_GROUP, 'test_users_group2']:
 
            users_group = UsersGroupModel().get_group(gr_name)
 
        for gr_name in [TEST_USER_GROUP, 'test_users_group2']:
 
            users_group = UserGroupModel().get_group(gr_name)
 
            ret = users_group.get_api_data()
 
            expected.append(ret)
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
        UsersGroupModel().delete(users_group='test_users_group2')
 
        UserGroupModel().delete(users_group='test_users_group2')
 
        Session().commit()
 

	
 
    def test_api_create_users_group(self):
 
        group_name = 'some_new_group'
 
        id_, params = _build_data(self.apikey, 'create_users_group',
 
                                  group_name=group_name)
 
        response = api_call(self, params)
 

	
 
        ret = {
 
            'msg': 'created new user group `%s`' % group_name,
 
            'users_group': jsonify(UsersGroupModel()\
 
            'users_group': jsonify(UserGroupModel()\
 
                                   .get_by_name(group_name)\
 
                                   .get_api_data())
 
        }
 
        expected = ret
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
        destroy_users_group(group_name)
 

	
 
    def test_api_get_users_group_that_exist(self):
 
        id_, params = _build_data(self.apikey, 'create_users_group',
 
                                  group_name=TEST_USERS_GROUP)
 
                                  group_name=TEST_USER_GROUP)
 
        response = api_call(self, params)
 

	
 
        expected = "user group `%s` already exist" % TEST_USERS_GROUP
 
        expected = "user group `%s` already exist" % TEST_USER_GROUP
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(UsersGroupModel, 'create', crash)
 
    @mock.patch.object(UserGroupModel, 'create', crash)
 
    def test_api_get_users_group_exception_occurred(self):
 
        group_name = 'exception_happens'
 
        id_, params = _build_data(self.apikey, 'create_users_group',
 
                                  group_name=group_name)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to create group `%s`' % group_name
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    def test_api_add_user_to_users_group(self):
 
        gr_name = 'test_group'
 
        UsersGroupModel().create(gr_name)
 
        UserGroupModel().create(gr_name)
 
        Session().commit()
 
        id_, params = _build_data(self.apikey, 'add_user_to_users_group',
 
                                  usersgroupid=gr_name,
 
                                  userid=TEST_USER_ADMIN_LOGIN)
 
        response = api_call(self, params)
 

	
 
        expected = {
 
                    'msg': 'added member `%s` to user group `%s`' % (
 
                                TEST_USER_ADMIN_LOGIN, gr_name
 
                            ),
 
                    'success': True}
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
        UsersGroupModel().delete(users_group=gr_name)
 
        UserGroupModel().delete(users_group=gr_name)
 
        Session().commit()
 

	
 
    def test_api_add_user_to_users_group_that_doesnt_exist(self):
 
        id_, params = _build_data(self.apikey, 'add_user_to_users_group',
 
                                  usersgroupid='false-group',
 
                                  userid=TEST_USER_ADMIN_LOGIN)
 
        response = api_call(self, params)
 

	
 
        expected = 'user group `%s` does not exist' % 'false-group'
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(UsersGroupModel, 'add_user_to_group', crash)
 
    @mock.patch.object(UserGroupModel, 'add_user_to_group', crash)
 
    def test_api_add_user_to_users_group_exception_occurred(self):
 
        gr_name = 'test_group'
 
        UsersGroupModel().create(gr_name)
 
        UserGroupModel().create(gr_name)
 
        Session().commit()
 
        id_, params = _build_data(self.apikey, 'add_user_to_users_group',
 
                                  usersgroupid=gr_name,
 
                                  userid=TEST_USER_ADMIN_LOGIN)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to add member to user group `%s`' % gr_name
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
        UsersGroupModel().delete(users_group=gr_name)
 
        UserGroupModel().delete(users_group=gr_name)
 
        Session().commit()
 

	
 
    def test_api_remove_user_from_users_group(self):
 
        gr_name = 'test_group_3'
 
        gr = UsersGroupModel().create(gr_name)
 
        UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
 
        gr = UserGroupModel().create(gr_name)
 
        UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
 
        Session().commit()
 
        id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
 
                                  usersgroupid=gr_name,
 
                                  userid=TEST_USER_ADMIN_LOGIN)
 
        response = api_call(self, params)
 

	
 
        expected = {
 
                    'msg': 'removed member `%s` from user group `%s`' % (
 
                                TEST_USER_ADMIN_LOGIN, gr_name
 
                            ),
 
                    'success': True}
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
        UsersGroupModel().delete(users_group=gr_name)
 
        UserGroupModel().delete(users_group=gr_name)
 
        Session().commit()
 

	
 
    @mock.patch.object(UsersGroupModel, 'remove_user_from_group', crash)
 
    @mock.patch.object(UserGroupModel, 'remove_user_from_group', crash)
 
    def test_api_remove_user_from_users_group_exception_occurred(self):
 
        gr_name = 'test_group_3'
 
        gr = UsersGroupModel().create(gr_name)
 
        UsersGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
 
        gr = UserGroupModel().create(gr_name)
 
        UserGroupModel().add_user_to_group(gr, user=TEST_USER_ADMIN_LOGIN)
 
        Session().commit()
 
        id_, params = _build_data(self.apikey, 'remove_user_from_users_group',
 
                                  usersgroupid=gr_name,
 
                                  userid=TEST_USER_ADMIN_LOGIN)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to remove member from user group `%s`' % gr_name
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
        UsersGroupModel().delete(users_group=gr_name)
 
        UserGroupModel().delete(users_group=gr_name)
 
        Session().commit()
 

	
 
    @parameterized.expand([('none', 'repository.none'),
 
                           ('read', 'repository.read'),
 
                           ('write', 'repository.write'),
 
                           ('admin', 'repository.admin')])
 
    def test_api_grant_user_permission(self, name, perm):
 
        id_, params = _build_data(self.apikey, 'grant_user_permission',
 
                                  repoid=self.REPO,
 
                                  userid=TEST_USER_ADMIN_LOGIN,
 
                                  perm=perm)
 
        response = api_call(self, params)
 

	
 
        ret = {
 
                'msg': 'Granted perm: `%s` for user: `%s` in repo: `%s`' % (
 
                    perm, TEST_USER_ADMIN_LOGIN, self.REPO
 
                ),
 
                'success': True
 
            }
 
        expected = ret
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
    def test_api_grant_user_permission_wrong_permission(self):
 
        perm = 'haha.no.permission'
 
        id_, params = _build_data(self.apikey, 'grant_user_permission',
 
                                  repoid=self.REPO,
 
                                  userid=TEST_USER_ADMIN_LOGIN,
 
                                  perm=perm)
 
        response = api_call(self, params)
 

	
 
        expected = 'permission `%s` does not exist' % perm
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(RepoModel, 'grant_user_permission', crash)
 
    def test_api_grant_user_permission_exception_when_adding(self):
 
        perm = 'repository.read'
 
        id_, params = _build_data(self.apikey, 'grant_user_permission',
 
                                  repoid=self.REPO,
 
                                  userid=TEST_USER_ADMIN_LOGIN,
 
                                  perm=perm)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
 
                    TEST_USER_ADMIN_LOGIN, self.REPO
 
                )
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    def test_api_revoke_user_permission(self):
 
        id_, params = _build_data(self.apikey, 'revoke_user_permission',
 
                                  repoid=self.REPO,
 
                                  userid=TEST_USER_ADMIN_LOGIN,)
 
        response = api_call(self, params)
 

	
 
        expected = {
 
            'msg': 'Revoked perm for user: `%s` in repo: `%s`' % (
 
                TEST_USER_ADMIN_LOGIN, self.REPO
 
            ),
 
            'success': True
 
        }
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(RepoModel, 'revoke_user_permission', crash)
 
    def test_api_revoke_user_permission_exception_when_adding(self):
 
        id_, params = _build_data(self.apikey, 'revoke_user_permission',
 
                                  repoid=self.REPO,
 
                                  userid=TEST_USER_ADMIN_LOGIN,)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to edit permission for user: `%s` in repo: `%s`' % (
 
                    TEST_USER_ADMIN_LOGIN, self.REPO
 
                )
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    @parameterized.expand([('none', 'repository.none'),
 
                           ('read', 'repository.read'),
 
                           ('write', 'repository.write'),
 
                           ('admin', 'repository.admin')])
 
    def test_api_grant_users_group_permission(self, name, perm):
 
        id_, params = _build_data(self.apikey, 'grant_users_group_permission',
 
                                  repoid=self.REPO,
 
                                  usersgroupid=TEST_USERS_GROUP,
 
                                  usersgroupid=TEST_USER_GROUP,
 
                                  perm=perm)
 
        response = api_call(self, params)
 

	
 
        ret = {
 
            'msg': 'Granted perm: `%s` for user group: `%s` in repo: `%s`' % (
 
                perm, TEST_USERS_GROUP, self.REPO
 
                perm, TEST_USER_GROUP, self.REPO
 
            ),
 
            'success': True
 
        }
 
        expected = ret
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
    def test_api_grant_users_group_permission_wrong_permission(self):
 
        perm = 'haha.no.permission'
 
        id_, params = _build_data(self.apikey, 'grant_users_group_permission',
 
                                  repoid=self.REPO,
 
                                  usersgroupid=TEST_USERS_GROUP,
 
                                  usersgroupid=TEST_USER_GROUP,
 
                                  perm=perm)
 
        response = api_call(self, params)
 

	
 
        expected = 'permission `%s` does not exist' % perm
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(RepoModel, 'grant_users_group_permission', crash)
 
    def test_api_grant_users_group_permission_exception_when_adding(self):
 
        perm = 'repository.read'
 
        id_, params = _build_data(self.apikey, 'grant_users_group_permission',
 
                                  repoid=self.REPO,
 
                                  usersgroupid=TEST_USERS_GROUP,
 
                                  usersgroupid=TEST_USER_GROUP,
 
                                  perm=perm)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
 
                    TEST_USERS_GROUP, self.REPO
 
                    TEST_USER_GROUP, self.REPO
 
                )
 
        self._compare_error(id_, expected, given=response.body)
 

	
 
    def test_api_revoke_users_group_permission(self):
 
        RepoModel().grant_users_group_permission(repo=self.REPO,
 
                                                 group_name=TEST_USERS_GROUP,
 
                                                 group_name=TEST_USER_GROUP,
 
                                                 perm='repository.read')
 
        Session().commit()
 
        id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
 
                                  repoid=self.REPO,
 
                                  usersgroupid=TEST_USERS_GROUP,)
 
                                  usersgroupid=TEST_USER_GROUP,)
 
        response = api_call(self, params)
 

	
 
        expected = {
 
            'msg': 'Revoked perm for user group: `%s` in repo: `%s`' % (
 
                TEST_USERS_GROUP, self.REPO
 
                TEST_USER_GROUP, self.REPO
 
            ),
 
            'success': True
 
        }
 
        self._compare_ok(id_, expected, given=response.body)
 

	
 
    @mock.patch.object(RepoModel, 'revoke_users_group_permission', crash)
 
    def test_api_revoke_users_group_permission_exception_when_adding(self):
 

	
 
        id_, params = _build_data(self.apikey, 'revoke_users_group_permission',
 
                                  repoid=self.REPO,
 
                                  usersgroupid=TEST_USERS_GROUP,)
 
                                  usersgroupid=TEST_USER_GROUP,)
 
        response = api_call(self, params)
 

	
 
        expected = 'failed to edit permission for user group: `%s` in repo: `%s`' % (
 
                    TEST_USERS_GROUP, self.REPO
 
                    TEST_USER_GROUP, self.REPO
 
                )
 
        self._compare_error(id_, expected, given=response.body)
rhodecode/tests/functional/test_admin_users_groups.py
Show inline comments
 
from rhodecode.tests import *
 
from rhodecode.model.db import UsersGroup, UsersGroupToPerm, Permission
 
from rhodecode.model.db import UserGroup, UserGroupToPerm, Permission
 

	
 
TEST_USERS_GROUP = 'admins_test'
 
TEST_USER_GROUP = 'admins_test'
 

	
 

	
 
class TestAdminUsersGroupsController(TestController):
 

	
 
    def test_index(self):
 
        response = self.app.get(url('users_groups'))
 
        # Test response...
 

	
 
    def test_index_as_xml(self):
 
        response = self.app.get(url('formatted_users_groups', format='xml'))
 

	
 
    def test_create(self):
 
        self.log_user()
 
        users_group_name = TEST_USERS_GROUP
 
        users_group_name = TEST_USER_GROUP
 
        response = self.app.post(url('users_groups'),
 
                                 {'users_group_name': users_group_name,
 
                                  'active':True})
 
        response.follow()
 

	
 
        self.checkSessionFlash(response,
 
                               'created user group %s' % TEST_USERS_GROUP)
 
                               'created user group %s' % TEST_USER_GROUP)
 

	
 
    def test_new(self):
 
        response = self.app.get(url('new_users_group'))
 

	
 
    def test_new_as_xml(self):
 
        response = self.app.get(url('formatted_new_users_group', format='xml'))
 

	
 
    def test_update(self):
 
        response = self.app.put(url('users_group', id=1))
 

	
 
    def test_update_browser_fakeout(self):
 
        response = self.app.post(url('users_group', id=1),
 
                                 params=dict(_method='put'))
 

	
 
    def test_delete(self):
 
        self.log_user()
 
        users_group_name = TEST_USERS_GROUP + 'another'
 
        users_group_name = TEST_USER_GROUP + 'another'
 
        response = self.app.post(url('users_groups'),
 
                                 {'users_group_name':users_group_name,
 
                                  'active':True})
 
        response.follow()
 

	
 
        self.checkSessionFlash(response,
 
                               'created user group %s' % users_group_name)
 

	
 
        gr = self.Session.query(UsersGroup)\
 
                           .filter(UsersGroup.users_group_name ==
 
        gr = self.Session.query(UserGroup)\
 
                           .filter(UserGroup.users_group_name ==
 
                                   users_group_name).one()
 

	
 
        response = self.app.delete(url('users_group', id=gr.users_group_id))
 

	
 
        gr = self.Session.query(UsersGroup)\
 
                           .filter(UsersGroup.users_group_name ==
 
        gr = self.Session.query(UserGroup)\
 
                           .filter(UserGroup.users_group_name ==
 
                                   users_group_name).scalar()
 

	
 
        self.assertEqual(gr, None)
 

	
 
    def test_enable_repository_read_on_group(self):
 
        self.log_user()
 
        users_group_name = TEST_USERS_GROUP + 'another2'
 
        users_group_name = TEST_USER_GROUP + 'another2'
 
        response = self.app.post(url('users_groups'),
 
                                 {'users_group_name': users_group_name,
 
                                  'active': True})
 
        response.follow()
 

	
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        self.checkSessionFlash(response,
 
                               'created user group %s' % users_group_name)
 
        ## ENABLE REPO CREATE ON A GROUP
 
        response = self.app.put(url('users_group_perm', id=ug.users_group_id),
 
                                 {'create_repo_perm': True})
 

	
 
        response.follow()
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        p = Permission.get_by_key('hg.create.repository')
 
        p2 = Permission.get_by_key('hg.fork.none')
 
        # check if user has this perms, they should be here since
 
        # defaults are on
 
        perms = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == ug).all()
 
        perms = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == ug).all()
 

	
 
        self.assertEqual(
 
            [[x.users_group_id, x.permission_id, ] for x in perms],
 
            [[ug.users_group_id, p.permission_id],
 
             [ug.users_group_id, p2.permission_id]]
 
        )
 

	
 
        ## DISABLE REPO CREATE ON A GROUP
 
        response = self.app.put(url('users_group_perm', id=ug.users_group_id),
 
                                    {})
 

	
 
        response.follow()
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        p = Permission.get_by_key('hg.create.none')
 
        p2 = Permission.get_by_key('hg.fork.none')
 
        # check if user has this perms, they should be here since
 
        # defaults are on
 
        perms = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == ug).all()
 
        perms = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == ug).all()
 

	
 
        self.assertEqual(
 
            sorted([[x.users_group_id, x.permission_id, ] for x in perms]),
 
            sorted([[ug.users_group_id, p.permission_id],
 
             [ug.users_group_id, p2.permission_id]])
 
        )
 

	
 
        # DELETE !
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        ugid = ug.users_group_id
 
        response = self.app.delete(url('users_group', id=ug.users_group_id))
 
        response = response.follow()
 
        gr = self.Session.query(UsersGroup)\
 
                           .filter(UsersGroup.users_group_name ==
 
        gr = self.Session.query(UserGroup)\
 
                           .filter(UserGroup.users_group_name ==
 
                                   users_group_name).scalar()
 

	
 
        self.assertEqual(gr, None)
 
        p = Permission.get_by_key('hg.create.repository')
 
        perms = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group_id == ugid).all()
 
        perms = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group_id == ugid).all()
 
        perms = [[x.users_group_id,
 
                  x.permission_id, ] for x in perms]
 
        self.assertEqual(
 
            perms,
 
            []
 
        )
 

	
 
    def test_enable_repository_fork_on_group(self):
 
        self.log_user()
 
        users_group_name = TEST_USERS_GROUP + 'another2'
 
        users_group_name = TEST_USER_GROUP + 'another2'
 
        response = self.app.post(url('users_groups'),
 
                                 {'users_group_name': users_group_name,
 
                                  'active': True})
 
        response.follow()
 

	
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        self.checkSessionFlash(response,
 
                               'created user group %s' % users_group_name)
 
        ## ENABLE REPO CREATE ON A GROUP
 
        response = self.app.put(url('users_group_perm', id=ug.users_group_id),
 
                                 {'fork_repo_perm': True})
 

	
 
        response.follow()
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        p = Permission.get_by_key('hg.create.none')
 
        p2 = Permission.get_by_key('hg.fork.repository')
 
        # check if user has this perms, they should be here since
 
        # defaults are on
 
        perms = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == ug).all()
 
        perms = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == ug).all()
 

	
 
        self.assertEqual(
 
            [[x.users_group_id, x.permission_id, ] for x in perms],
 
            [[ug.users_group_id, p.permission_id],
 
             [ug.users_group_id, p2.permission_id]]
 
        )
 

	
 
        ## DISABLE REPO CREATE ON A GROUP
 
        response = self.app.put(url('users_group_perm', id=ug.users_group_id),
 
                                    {})
 

	
 
        response.follow()
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        p = Permission.get_by_key('hg.create.none')
 
        p2 = Permission.get_by_key('hg.fork.none')
 
        # check if user has this perms, they should be here since
 
        # defaults are on
 
        perms = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group == ug).all()
 
        perms = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group == ug).all()
 

	
 
        self.assertEqual(
 
            [[x.users_group_id, x.permission_id, ] for x in perms],
 
            [[ug.users_group_id, p.permission_id],
 
             [ug.users_group_id, p2.permission_id]]
 
        )
 

	
 
        # DELETE !
 
        ug = UsersGroup.get_by_group_name(users_group_name)
 
        ug = UserGroup.get_by_group_name(users_group_name)
 
        ugid = ug.users_group_id
 
        response = self.app.delete(url('users_group', id=ug.users_group_id))
 
        response = response.follow()
 
        gr = self.Session.query(UsersGroup)\
 
                           .filter(UsersGroup.users_group_name ==
 
        gr = self.Session.query(UserGroup)\
 
                           .filter(UserGroup.users_group_name ==
 
                                   users_group_name).scalar()
 

	
 
        self.assertEqual(gr, None)
 
        p = Permission.get_by_key('hg.fork.repository')
 
        perms = UsersGroupToPerm.query()\
 
            .filter(UsersGroupToPerm.users_group_id == ugid).all()
 
        perms = UserGroupToPerm.query()\
 
            .filter(UserGroupToPerm.users_group_id == ugid).all()
 
        perms = [[x.users_group_id,
 
                  x.permission_id, ] for x in perms]
 
        self.assertEqual(
 
            perms,
 
            []
 
        )
 

	
 
    def test_delete_browser_fakeout(self):
 
        response = self.app.post(url('users_group', id=1),
 
                                 params=dict(_method='delete'))
 

	
 
    def test_show(self):
 
        response = self.app.get(url('users_group', id=1))
 

	
 
    def test_show_as_xml(self):
 
        response = self.app.get(url('formatted_users_group', id=1, format='xml'))
 

	
 
    def test_edit(self):
 
        response = self.app.get(url('edit_users_group', id=1))
 

	
 
    def test_edit_as_xml(self):
 
        response = self.app.get(url('formatted_edit_users_group', id=1, format='xml'))
 

	
 
    def test_assign_members(self):
 
        pass
 

	
 
    def test_add_create_permission(self):
 
        pass
 

	
 
    def test_revoke_members(self):
 
        pass
rhodecode/tests/models/test_permissions.py
Show inline comments
 
import os
 
import unittest
 
from rhodecode.tests import *
 
from rhodecode.tests.models.common import _make_group
 
from rhodecode.model.repos_group import ReposGroupModel
 
from rhodecode.model.repo import RepoModel
 
from rhodecode.model.db import RepoGroup, User, UsersGroupRepoGroupToPerm
 
from rhodecode.model.db import RepoGroup, User, UserGroupRepoGroupToPerm
 
from rhodecode.model.user import UserModel
 

	
 
from rhodecode.model.meta import Session
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 
from rhodecode.lib.auth import AuthUser
 
from rhodecode.tests.api.api_base import create_repo
 

	
 

	
 
class TestPermissions(unittest.TestCase):
 
    def __init__(self, methodName='runTest'):
 
        super(TestPermissions, self).__init__(methodName=methodName)
 

	
 
    def setUp(self):
 
        self.u1 = UserModel().create_or_update(
 
            username=u'u1', password=u'qweqwe',
 
            email=u'u1@rhodecode.org', firstname=u'u1', lastname=u'u1'
 
        )
 
        self.u2 = UserModel().create_or_update(
 
            username=u'u2', password=u'qweqwe',
 
            email=u'u2@rhodecode.org', firstname=u'u2', lastname=u'u2'
 
        )
 
        self.u3 = UserModel().create_or_update(
 
            username=u'u3', password=u'qweqwe',
 
            email=u'u3@rhodecode.org', firstname=u'u3', lastname=u'u3'
 
        )
 
        self.anon = User.get_by_username('default')
 
        self.a1 = UserModel().create_or_update(
 
            username=u'a1', password=u'qweqwe',
 
            email=u'a1@rhodecode.org', firstname=u'a1', lastname=u'a1', admin=True
 
        )
 
        Session().commit()
 

	
 
    def tearDown(self):
 
        if hasattr(self, 'test_repo'):
 
            RepoModel().delete(repo=self.test_repo)
 

	
 
        UserModel().delete(self.u1)
 
        UserModel().delete(self.u2)
 
        UserModel().delete(self.u3)
 
        UserModel().delete(self.a1)
 
        if hasattr(self, 'g1'):
 
            ReposGroupModel().delete(self.g1.group_id)
 
        if hasattr(self, 'g2'):
 
            ReposGroupModel().delete(self.g2.group_id)
 

	
 
        if hasattr(self, 'ug1'):
 
            UsersGroupModel().delete(self.ug1, force=True)
 
            UserGroupModel().delete(self.ug1, force=True)
 

	
 
        Session().commit()
 

	
 
    def test_default_perms_set(self):
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        perms = {
 
            'repositories_groups': {},
 
            'global': set([u'hg.create.repository', u'repository.read',
 
                           u'hg.register.manual_activate']),
 
            'repositories': {u'vcs_test_hg': u'repository.read'}
 
        }
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         perms['repositories'][HG_REPO])
 
        new_perm = 'repository.write'
 
        RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
 
                                          perm=new_perm)
 
        Session().commit()
 

	
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         new_perm)
 

	
 
    def test_default_admin_perms_set(self):
 
        a1_auth = AuthUser(user_id=self.a1.user_id)
 
        perms = {
 
            'repositories_groups': {},
 
            'global': set([u'hg.admin']),
 
            'repositories': {u'vcs_test_hg': u'repository.admin'}
 
        }
 
        self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
 
                         perms['repositories'][HG_REPO])
 
        new_perm = 'repository.write'
 
        RepoModel().grant_user_permission(repo=HG_REPO, user=self.a1,
 
                                          perm=new_perm)
 
        Session().commit()
 
        # cannot really downgrade admins permissions !? they still get's set as
 
        # admin !
 
        u1_auth = AuthUser(user_id=self.a1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         perms['repositories'][HG_REPO])
 

	
 
    def test_default_group_perms(self):
 
        self.g1 = _make_group('test1', skip_if_exists=True)
 
        self.g2 = _make_group('test2', skip_if_exists=True)
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        perms = {
 
            'repositories_groups': {u'test1': 'group.read', u'test2': 'group.read'},
 
            'global': set([u'hg.create.repository', u'repository.read', u'hg.register.manual_activate']),
 
            'repositories': {u'vcs_test_hg': u'repository.read'}
 
        }
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         perms['repositories'][HG_REPO])
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                         perms['repositories_groups'])
 

	
 
    def test_default_admin_group_perms(self):
 
        self.g1 = _make_group('test1', skip_if_exists=True)
 
        self.g2 = _make_group('test2', skip_if_exists=True)
 
        a1_auth = AuthUser(user_id=self.a1.user_id)
 
        perms = {
 
            'repositories_groups': {u'test1': 'group.admin', u'test2': 'group.admin'},
 
            'global': set(['hg.admin']),
 
            'repositories': {u'vcs_test_hg': 'repository.admin'}
 
        }
 

	
 
        self.assertEqual(a1_auth.permissions['repositories'][HG_REPO],
 
                         perms['repositories'][HG_REPO])
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                         perms['repositories_groups'])
 

	
 
    def test_propagated_permission_from_users_group_by_explicit_perms_exist(self):
 
        # make group
 
        self.ug1 = UsersGroupModel().create('G1')
 
        self.ug1 = UserGroupModel().create('G1')
 
        # add user to group
 

	
 
        UsersGroupModel().add_user_to_group(self.ug1, self.u1)
 
        UserGroupModel().add_user_to_group(self.ug1, self.u1)
 

	
 
        # set permission to lower
 
        new_perm = 'repository.none'
 
        RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm)
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         new_perm)
 

	
 
        # grant perm for group this should not override permission from user
 
        # since it has explicitly set
 
        new_perm_gr = 'repository.write'
 
        RepoModel().grant_users_group_permission(repo=HG_REPO,
 
                                                 group_name=self.ug1,
 
                                                 perm=new_perm_gr)
 
        # check perms
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        perms = {
 
            'repositories_groups': {},
 
            'global': set([u'hg.create.repository', u'repository.read',
 
                           u'hg.register.manual_activate']),
 
            'repositories': {u'vcs_test_hg': u'repository.read'}
 
        }
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         new_perm)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                         perms['repositories_groups'])
 

	
 
    def test_propagated_permission_from_users_group(self):
 
        # make group
 
        self.ug1 = UsersGroupModel().create('G1')
 
        self.ug1 = UserGroupModel().create('G1')
 
        # add user to group
 

	
 
        UsersGroupModel().add_user_to_group(self.ug1, self.u3)
 
        UserGroupModel().add_user_to_group(self.ug1, self.u3)
 

	
 
        # grant perm for group this should override default permission from user
 
        new_perm_gr = 'repository.write'
 
        RepoModel().grant_users_group_permission(repo=HG_REPO,
 
                                                 group_name=self.ug1,
 
                                                 perm=new_perm_gr)
 
        # check perms
 
        u3_auth = AuthUser(user_id=self.u3.user_id)
 
        perms = {
 
            'repositories_groups': {},
 
            'global': set([u'hg.create.repository', u'repository.read',
 
                           u'hg.register.manual_activate']),
 
            'repositories': {u'vcs_test_hg': u'repository.read'}
 
        }
 
        self.assertEqual(u3_auth.permissions['repositories'][HG_REPO],
 
                         new_perm_gr)
 
        self.assertEqual(u3_auth.permissions['repositories_groups'],
 
                         perms['repositories_groups'])
 

	
 
    def test_propagated_permission_from_users_group_lower_weight(self):
 
        # make group
 
        self.ug1 = UsersGroupModel().create('G1')
 
        self.ug1 = UserGroupModel().create('G1')
 
        # add user to group
 
        UsersGroupModel().add_user_to_group(self.ug1, self.u1)
 
        UserGroupModel().add_user_to_group(self.ug1, self.u1)
 

	
 
        # set permission to lower
 
        new_perm_h = 'repository.write'
 
        RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1,
 
                                          perm=new_perm_h)
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         new_perm_h)
 

	
 
        # grant perm for group this should NOT override permission from user
 
        # since it's lower than granted
 
        new_perm_l = 'repository.read'
 
        RepoModel().grant_users_group_permission(repo=HG_REPO,
 
                                                 group_name=self.ug1,
 
                                                 perm=new_perm_l)
 
        # check perms
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        perms = {
 
            'repositories_groups': {},
 
            'global': set([u'hg.create.repository', u'repository.read',
 
                           u'hg.register.manual_activate']),
 
            'repositories': {u'vcs_test_hg': u'repository.write'}
 
        }
 
        self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
 
                         new_perm_h)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                         perms['repositories_groups'])
 

	
 
    def test_repo_in_group_permissions(self):
 
        self.g1 = _make_group('group1', skip_if_exists=True)
 
        self.g2 = _make_group('group2', skip_if_exists=True)
 
        Session().commit()
 
        # both perms should be read !
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                         {u'group1': u'group.read', u'group2': u'group.read'})
 

	
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.read', u'group2': u'group.read'})
 

	
 
        #Change perms to none for both groups
 
        ReposGroupModel().grant_user_permission(repos_group=self.g1,
 
                                                user=self.anon,
 
                                                perm='group.none')
 
        ReposGroupModel().grant_user_permission(repos_group=self.g2,
 
                                                user=self.anon,
 
                                                perm='group.none')
 

	
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.none', u'group2': u'group.none'})
 

	
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.none', u'group2': u'group.none'})
 

	
 
        # add repo to group
 
        name = RepoGroup.url_sep().join([self.g1.group_name, 'test_perm'])
 
        self.test_repo = RepoModel().create_repo(
 
            repo_name=name,
 
            repo_type='hg',
 
            description='',
 
            repos_group=self.g1,
 
            owner=self.u1,
 
        )
 
        Session().commit()
 

	
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.none', u'group2': u'group.none'})
 

	
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.none', u'group2': u'group.none'})
 

	
 
        #grant permission for u2 !
 
        ReposGroupModel().grant_user_permission(repos_group=self.g1,
 
                                                user=self.u2,
 
                                                perm='group.read')
 
        ReposGroupModel().grant_user_permission(repos_group=self.g2,
 
                                                user=self.u2,
 
                                                perm='group.read')
 
        Session().commit()
 
        self.assertNotEqual(self.u1, self.u2)
 
        #u1 and anon should have not change perms while u2 should !
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.none', u'group2': u'group.none'})
 

	
 
        u2_auth = AuthUser(user_id=self.u2.user_id)
 
        self.assertEqual(u2_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.read', u'group2': u'group.read'})
 

	
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                 {u'group1': u'group.none', u'group2': u'group.none'})
 

	
 
    def test_repo_group_user_as_user_group_member(self):
 
        # create Group1
 
        self.g1 = _make_group('group1', skip_if_exists=True)
 
        Session().commit()
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 

	
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                         {u'group1': u'group.read'})
 

	
 
        # set default permission to none
 
        ReposGroupModel().grant_user_permission(repos_group=self.g1,
 
                                                user=self.anon,
 
                                                perm='group.none')
 
        # make group
 
        self.ug1 = UsersGroupModel().create('G1')
 
        self.ug1 = UserGroupModel().create('G1')
 
        # add user to group
 
        UsersGroupModel().add_user_to_group(self.ug1, self.u1)
 
        UserGroupModel().add_user_to_group(self.ug1, self.u1)
 
        Session().commit()
 

	
 
        # check if user is in the group
 
        membrs = [x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members]
 
        membrs = [x.user_id for x in UserGroupModel().get(self.ug1.users_group_id).members]
 
        self.assertEqual(membrs, [self.u1.user_id])
 
        # add some user to that group
 

	
 
        # check his permissions
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                         {u'group1': u'group.none'})
 

	
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                         {u'group1': u'group.none'})
 

	
 
        # grant ug1 read permissions for
 
        ReposGroupModel().grant_users_group_permission(repos_group=self.g1,
 
                                                       group_name=self.ug1,
 
                                                       perm='group.read')
 
        Session().commit()
 
        # check if the
 
        obj = Session().query(UsersGroupRepoGroupToPerm)\
 
            .filter(UsersGroupRepoGroupToPerm.group == self.g1)\
 
            .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\
 
        obj = Session().query(UserGroupRepoGroupToPerm)\
 
            .filter(UserGroupRepoGroupToPerm.group == self.g1)\
 
            .filter(UserGroupRepoGroupToPerm.users_group == self.ug1)\
 
            .scalar()
 
        self.assertEqual(obj.permission.permission_name, 'group.read')
 

	
 
        a1_auth = AuthUser(user_id=self.anon.user_id)
 

	
 
        self.assertEqual(a1_auth.permissions['repositories_groups'],
 
                         {u'group1': u'group.none'})
 

	
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories_groups'],
 
                         {u'group1': u'group.read'})
 

	
 
    def test_inherited_permissions_from_default_on_user_enabled(self):
 
        user_model = UserModel()
 
        # enable fork and create on default user
 
        usr = 'default'
 
        user_model.revoke_perm(usr, 'hg.create.none')
 
        user_model.grant_perm(usr, 'hg.create.repository')
 
        user_model.revoke_perm(usr, 'hg.fork.none')
 
        user_model.grant_perm(usr, 'hg.fork.repository')
 
        # make sure inherit flag is turned on
 
        self.u1.inherit_default_permissions = True
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        # this user will have inherited permissions from default user
 
        self.assertEqual(u1_auth.permissions['global'],
 
                         set(['hg.create.repository', 'hg.fork.repository',
 
                              'hg.register.manual_activate',
 
                              'repository.read', 'group.read']))
 

	
 
    def test_inherited_permissions_from_default_on_user_disabled(self):
 
        user_model = UserModel()
 
        # disable fork and create on default user
 
        usr = 'default'
 
        user_model.revoke_perm(usr, 'hg.create.repository')
 
        user_model.grant_perm(usr, 'hg.create.none')
 
        user_model.revoke_perm(usr, 'hg.fork.repository')
 
        user_model.grant_perm(usr, 'hg.fork.none')
 
        # make sure inherit flag is turned on
 
        self.u1.inherit_default_permissions = True
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        # this user will have inherited permissions from default user
 
        self.assertEqual(u1_auth.permissions['global'],
 
                         set(['hg.create.none', 'hg.fork.none',
 
                              'hg.register.manual_activate',
 
                              'repository.read', 'group.read']))
 

	
 
    def test_non_inherited_permissions_from_default_on_user_enabled(self):
 
        user_model = UserModel()
 
        # enable fork and create on default user
 
        usr = 'default'
 
        user_model.revoke_perm(usr, 'hg.create.none')
 
        user_model.grant_perm(usr, 'hg.create.repository')
 
        user_model.revoke_perm(usr, 'hg.fork.none')
 
        user_model.grant_perm(usr, 'hg.fork.repository')
 

	
 
        #disable global perms on specific user
 
        user_model.revoke_perm(self.u1, 'hg.create.repository')
 
        user_model.grant_perm(self.u1, 'hg.create.none')
 
        user_model.revoke_perm(self.u1, 'hg.fork.repository')
 
        user_model.grant_perm(self.u1, 'hg.fork.none')
 

	
 
        # make sure inherit flag is turned off
 
        self.u1.inherit_default_permissions = False
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        # this user will have non inherited permissions from he's
 
        # explicitly set permissions
 
        self.assertEqual(u1_auth.permissions['global'],
 
                         set(['hg.create.none', 'hg.fork.none',
 
                              'hg.register.manual_activate',
 
                              'repository.read', 'group.read']))
 

	
 
    def test_non_inherited_permissions_from_default_on_user_disabled(self):
 
        user_model = UserModel()
 
        # disable fork and create on default user
 
        usr = 'default'
 
        user_model.revoke_perm(usr, 'hg.create.repository')
 
        user_model.grant_perm(usr, 'hg.create.none')
 
        user_model.revoke_perm(usr, 'hg.fork.repository')
 
        user_model.grant_perm(usr, 'hg.fork.none')
 

	
 
        #enable global perms on specific user
 
        user_model.revoke_perm(self.u1, 'hg.create.none')
 
        user_model.grant_perm(self.u1, 'hg.create.repository')
 
        user_model.revoke_perm(self.u1, 'hg.fork.none')
 
        user_model.grant_perm(self.u1, 'hg.fork.repository')
 

	
 
        # make sure inherit flag is turned off
 
        self.u1.inherit_default_permissions = False
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        # this user will have non inherited permissions from he's
 
        # explicitly set permissions
 
        self.assertEqual(u1_auth.permissions['global'],
 
                         set(['hg.create.repository', 'hg.fork.repository',
 
                              'hg.register.manual_activate',
 
                              'repository.read', 'group.read']))
 

	
 
    def test_owner_permissions_doesnot_get_overwritten_by_group(self):
 
        #create repo as USER,
 
        self.test_repo = repo = RepoModel().create_repo(repo_name='myownrepo',
 
                                repo_type='hg',
 
                                description='desc',
 
                                owner=self.u1)
 

	
 
        Session().commit()
 
        #he has permissions of admin as owner
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
 
                         'repository.admin')
 
        #set his permission as user group, he should still be admin
 
        self.ug1 = UsersGroupModel().create('G1')
 
        self.ug1 = UserGroupModel().create('G1')
 
        # add user to group
 
        UsersGroupModel().add_user_to_group(self.ug1, self.u1)
 
        UserGroupModel().add_user_to_group(self.ug1, self.u1)
 
        RepoModel().grant_users_group_permission(repo, group_name=self.ug1,
 
                                                 perm='repository.none')
 

	
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
 
                         'repository.admin')
 

	
 
    def test_owner_permissions_doesnot_get_overwritten_by_others(self):
 
        #create repo as USER,
 
        self.test_repo = repo = RepoModel().create_repo(repo_name='myownrepo',
 
                                repo_type='hg',
 
                                description='desc',
 
                                owner=self.u1)
 

	
 
        Session().commit()
 
        #he has permissions of admin as owner
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
 
                         'repository.admin')
 
        #set his permission as user, he should still be admin
 
        RepoModel().grant_user_permission(repo, user=self.u1,
 
                                          perm='repository.none')
 
        Session().commit()
 
        u1_auth = AuthUser(user_id=self.u1.user_id)
 
        self.assertEqual(u1_auth.permissions['repositories']['myownrepo'],
 
                         'repository.admin')
rhodecode/tests/models/test_users.py
Show inline comments
 
import unittest
 
from rhodecode.tests import *
 

	
 
from rhodecode.model.db import User, UsersGroup, UsersGroupMember, UserEmailMap,\
 
from rhodecode.model.db import User, UserGroup, UserGroupMember, UserEmailMap,\
 
    Permission
 
from rhodecode.model.user import UserModel
 

	
 
from rhodecode.model.meta import Session
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 

	
 

	
 
class TestUser(unittest.TestCase):
 
    def __init__(self, methodName='runTest'):
 
        Session.remove()
 
        super(TestUser, self).__init__(methodName=methodName)
 

	
 
    def test_create_and_remove(self):
 
        usr = UserModel().create_or_update(username=u'test_user',
 
                                           password=u'qweqwe',
 
                                     email=u'u232@rhodecode.org',
 
                                     firstname=u'u1', lastname=u'u1')
 
        Session().commit()
 
        self.assertEqual(User.get_by_username(u'test_user'), usr)
 

	
 
        # make user group
 
        users_group = UsersGroupModel().create('some_example_group')
 
        users_group = UserGroupModel().create('some_example_group')
 
        Session().commit()
 

	
 
        UsersGroupModel().add_user_to_group(users_group, usr)
 
        UserGroupModel().add_user_to_group(users_group, usr)
 
        Session().commit()
 

	
 
        self.assertEqual(UsersGroup.get(users_group.users_group_id), users_group)
 
        self.assertEqual(UsersGroupMember.query().count(), 1)
 
        self.assertEqual(UserGroup.get(users_group.users_group_id), users_group)
 
        self.assertEqual(UserGroupMember.query().count(), 1)
 
        UserModel().delete(usr.user_id)
 
        Session().commit()
 

	
 
        self.assertEqual(UsersGroupMember.query().all(), [])
 
        self.assertEqual(UserGroupMember.query().all(), [])
 

	
 
    def test_additonal_email_as_main(self):
 
        usr = UserModel().create_or_update(username=u'test_user',
 
                                           password=u'qweqwe',
 
                                     email=u'main_email@rhodecode.org',
 
                                     firstname=u'u1', lastname=u'u1')
 
        Session().commit()
 

	
 
        def do():
 
            m = UserEmailMap()
 
            m.email = u'main_email@rhodecode.org'
 
            m.user = usr
 
            Session().add(m)
 
            Session().commit()
 
        self.assertRaises(AttributeError, do)
 

	
 
        UserModel().delete(usr.user_id)
 
        Session().commit()
 

	
 
    def test_extra_email_map(self):
 
        usr = UserModel().create_or_update(username=u'test_user',
 
                                           password=u'qweqwe',
 
                                     email=u'main_email@rhodecode.org',
 
                                     firstname=u'u1', lastname=u'u1')
 
        Session().commit()
 

	
 
        m = UserEmailMap()
 
        m.email = u'main_email2@rhodecode.org'
 
        m.user = usr
 
        Session().add(m)
 
        Session().commit()
 

	
 
        u = User.get_by_email(email='main_email@rhodecode.org')
 
        self.assertEqual(usr.user_id, u.user_id)
 
        self.assertEqual(usr.username, u.username)
 

	
 
        u = User.get_by_email(email='main_email2@rhodecode.org')
 
        self.assertEqual(usr.user_id, u.user_id)
 
        self.assertEqual(usr.username, u.username)
 
        u = User.get_by_email(email='main_email3@rhodecode.org')
 
        self.assertEqual(None, u)
 

	
 
        UserModel().delete(usr.user_id)
 
        Session().commit()
 

	
 

	
 
class TestUsers(unittest.TestCase):
 

	
 
    def __init__(self, methodName='runTest'):
 
        super(TestUsers, self).__init__(methodName=methodName)
 

	
 
    def setUp(self):
 
        self.u1 = UserModel().create_or_update(username=u'u1',
 
                                        password=u'qweqwe',
 
                                        email=u'u1@rhodecode.org',
 
                                        firstname=u'u1', lastname=u'u1')
 

	
 
    def tearDown(self):
 
        perm = Permission.query().all()
 
        for p in perm:
 
            UserModel().revoke_perm(self.u1, p)
 

	
 
        UserModel().delete(self.u1)
 
        Session().commit()
 

	
 
    def test_add_perm(self):
 
        perm = Permission.query().all()[0]
 
        UserModel().grant_perm(self.u1, perm)
 
        Session().commit()
 
        self.assertEqual(UserModel().has_perm(self.u1, perm), True)
 

	
 
    def test_has_perm(self):
 
        perm = Permission.query().all()
 
        for p in perm:
 
            has_p = UserModel().has_perm(self.u1, p)
 
            self.assertEqual(False, has_p)
 

	
 
    def test_revoke_perm(self):
 
        perm = Permission.query().all()[0]
 
        UserModel().grant_perm(self.u1, perm)
 
        Session().commit()
 
        self.assertEqual(UserModel().has_perm(self.u1, perm), True)
 

	
 
        #revoke
 
        UserModel().revoke_perm(self.u1, perm)
 
        Session().commit()
 
        self.assertEqual(UserModel().has_perm(self.u1, perm), False)
rhodecode/tests/models/test_users_group_permissions_on_groups.py
Show inline comments
 
import os
 
import unittest
 
import functools
 
from rhodecode.tests import *
 

	
 
from rhodecode.model.repos_group import ReposGroupModel
 
from rhodecode.model.db import RepoGroup, Repository, User
 

	
 
from rhodecode.model.meta import Session
 
from nose.tools import with_setup
 
from rhodecode.tests.models.common import _create_project_tree, check_tree_perms, \
 
    _get_perms, _check_expected_count, expected_count, _destroy_project_tree
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 
from rhodecode.model.repo import RepoModel
 

	
 

	
 
test_u2_id = None
 
test_u2_gr_id = None
 
_get_repo_perms = None
 
_get_group_perms = None
 

	
 

	
 
def permissions_setup_func(group_name='g0', perm='group.read', recursive=True):
 
    """
 
    Resets all permissions to perm attribute
 
    """
 
    repos_group = RepoGroup.get_by_group_name(group_name=group_name)
 
    if not repos_group:
 
        raise Exception('Cannot get group %s' % group_name)
 
    perms_updates = [[test_u2_gr_id, perm, 'users_group']]
 
    ReposGroupModel()._update_permissions(repos_group,
 
                                          perms_updates=perms_updates,
 
                                          recursive=recursive)
 
    Session().commit()
 

	
 

	
 
def setup_module():
 
    global test_u2_id, test_u2_gr_id, _get_repo_perms, _get_group_perms
 
    test_u2 = _create_project_tree()
 
    Session().commit()
 
    test_u2_id = test_u2.user_id
 

	
 
    gr1 = UsersGroupModel().create(name='perms_group_1')
 
    gr1 = UserGroupModel().create(name='perms_group_1')
 
    Session().commit()
 
    test_u2_gr_id = gr1.users_group_id
 
    UsersGroupModel().add_user_to_group(gr1, user=test_u2_id)
 
    UserGroupModel().add_user_to_group(gr1, user=test_u2_id)
 
    Session().commit()
 

	
 
    _get_repo_perms = functools.partial(_get_perms, key='repositories',
 
                                        test_u1_id=test_u2_id)
 
    _get_group_perms = functools.partial(_get_perms, key='repositories_groups',
 
                                         test_u1_id=test_u2_id)
 

	
 

	
 
def teardown_module():
 
    _destroy_project_tree(test_u2_id)
 

	
 

	
 
@with_setup(permissions_setup_func)
 
def test_user_permissions_on_group_without_recursive_mode():
 
    # set permission to g0 non-recursive mode
 
    recursive = False
 
    group = 'g0'
 
    permissions_setup_func(group, 'group.write', recursive=recursive)
 

	
 
    items = [x for x in _get_repo_perms(group, recursive)]
 
    expected = 0
 
    assert len(items) == expected, ' %s != %s' % (len(items), expected)
 
    for name, perm in items:
 
        yield check_tree_perms, name, perm, group, 'repository.read'
 

	
 
    items = [x for x in _get_group_perms(group, recursive)]
 
    expected = 1
 
    assert len(items) == expected, ' %s != %s' % (len(items), expected)
 
    for name, perm in items:
 
        yield check_tree_perms, name, perm, group, 'group.write'
 

	
 

	
 
@with_setup(permissions_setup_func)
 
def test_user_permissions_on_group_without_recursive_mode_subgroup():
 
    # set permission to g0 non-recursive mode
 
    recursive = False
 
    group = 'g0/g0_1'
 
    permissions_setup_func(group, 'group.write', recursive=recursive)
 

	
 
    items = [x for x in _get_repo_perms(group, recursive)]
 
    expected = 0
 
    assert len(items) == expected, ' %s != %s' % (len(items), expected)
 
    for name, perm in items:
 
        yield check_tree_perms, name, perm, group, 'repository.read'
 

	
 
    items = [x for x in _get_group_perms(group, recursive)]
 
    expected = 1
 
    assert len(items) == expected, ' %s != %s' % (len(items), expected)
 
    for name, perm in items:
 
        yield check_tree_perms, name, perm, group, 'group.write'
 

	
 

	
 
@with_setup(permissions_setup_func)
 
def test_user_permissions_on_group_with_recursive_mode():
 

	
 
    # set permission to g0 recursive mode, all children including
 
    # other repos and groups should have this permission now set !
 
    recursive = True
 
    group = 'g0'
 
    permissions_setup_func(group, 'group.write', recursive=recursive)
 

	
 
    repo_items = [x for x in _get_repo_perms(group, recursive)]
 
    items = [x for x in _get_group_perms(group, recursive)]
 
    _check_expected_count(items, repo_items, expected_count(group, True))
 

	
 
    for name, perm in repo_items:
 
        yield check_tree_perms, name, perm, group, 'repository.write'
 

	
 
    for name, perm in items:
 
        yield check_tree_perms, name, perm, group, 'group.write'
 

	
 

	
 
@with_setup(permissions_setup_func)
 
def test_user_permissions_on_group_with_recursive_mode_inner_group():
 
    ## set permission to g0_3 group to none
 
    recursive = True
 
    group = 'g0/g0_3'
 
    permissions_setup_func(group, 'group.none', recursive=recursive)
 

	
 
    repo_items = [x for x in _get_repo_perms(group, recursive)]
 
    items = [x for x in _get_group_perms(group, recursive)]
 
    _check_expected_count(items, repo_items, expected_count(group, True))
 

	
 
    for name, perm in repo_items:
 
        yield check_tree_perms, name, perm, group, 'repository.none'
 

	
 
    for name, perm in items:
 
        yield check_tree_perms, name, perm, group, 'group.none'
 

	
 

	
 
@with_setup(permissions_setup_func)
 
def test_user_permissions_on_group_with_recursive_mode_deepest():
 
    ## set permission to g0_3 group to none
 
    recursive = True
 
    group = 'g0/g0_1/g0_1_1'
 
    permissions_setup_func(group, 'group.write', recursive=recursive)
rhodecode/tests/test_validators.py
Show inline comments
 
# -*- coding: utf-8 -*-
 
import unittest
 
import formencode
 

	
 
from rhodecode.tests import *
 

	
 
from rhodecode.model import validators as v
 
from rhodecode.model.users_group import UsersGroupModel
 
from rhodecode.model.users_group import UserGroupModel
 

	
 
from rhodecode.model.meta import Session
 
from rhodecode.model.repos_group import ReposGroupModel
 
from rhodecode.config.routing import ADMIN_PREFIX
 
from rhodecode.model.db import ChangesetStatus, Repository
 
from rhodecode.model.changeset_status import ChangesetStatusModel
 
from rhodecode.model.comment import ChangesetCommentsModel
 

	
 

	
 
class TestReposGroups(unittest.TestCase):
 

	
 
    def setUp(self):
 
        pass
 

	
 
    def tearDown(self):
 
        pass
 

	
 
    def test_Message_extractor(self):
 
        validator = v.ValidUsername()
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'default')
 

	
 
        class StateObj(object):
 
            pass
 

	
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, 'default', StateObj)
 

	
 
    def test_ValidUsername(self):
 
        validator = v.ValidUsername()
 

	
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'default')
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'new_user')
 
        self.assertRaises(formencode.Invalid, validator.to_python, '.,')
 
        self.assertRaises(formencode.Invalid, validator.to_python,
 
                          TEST_USER_ADMIN_LOGIN)
 
        self.assertEqual('test', validator.to_python('test'))
 

	
 
        validator = v.ValidUsername(edit=True, old_data={'user_id': 1})
 

	
 
    def test_ValidRepoUser(self):
 
        validator = v.ValidRepoUser()
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'nouser')
 
        self.assertEqual(TEST_USER_ADMIN_LOGIN,
 
                         validator.to_python(TEST_USER_ADMIN_LOGIN))
 

	
 
    def test_ValidUsersGroup(self):
 
        validator = v.ValidUsersGroup()
 
    def test_ValidUserGroup(self):
 
        validator = v.ValidUserGroup()
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'default')
 
        self.assertRaises(formencode.Invalid, validator.to_python, '.,')
 

	
 
        gr = UsersGroupModel().create('test')
 
        gr2 = UsersGroupModel().create('tes2')
 
        gr = UserGroupModel().create('test')
 
        gr2 = UserGroupModel().create('tes2')
 
        Session.commit()
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'test')
 
        assert gr.users_group_id != None
 
        validator = v.ValidUsersGroup(edit=True,
 
        validator = v.ValidUserGroup(edit=True,
 
                                    old_data={'users_group_id':
 
                                              gr2.users_group_id})
 

	
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'test')
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'TesT')
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'TEST')
 
        UsersGroupModel().delete(gr)
 
        UsersGroupModel().delete(gr2)
 
        UserGroupModel().delete(gr)
 
        UserGroupModel().delete(gr2)
 
        Session.commit()
 

	
 
    def test_ValidReposGroup(self):
 
        validator = v.ValidReposGroup()
 
        model = ReposGroupModel()
 
        self.assertRaises(formencode.Invalid, validator.to_python,
 
                          {'group_name': HG_REPO, })
 
        gr = model.create(group_name='test_gr', group_description='desc',
 
                          parent=None,
 
                          just_db=True,
 
                          owner=TEST_USER_ADMIN_LOGIN)
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, {'group_name': gr.group_name, })
 

	
 
        validator = v.ValidReposGroup(edit=True,
 
                                      old_data={'group_id':  gr.group_id})
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, {
 
                                        'group_name': gr.group_name + 'n',
 
                                        'group_parent_id': gr.group_id
 
                                        })
 
        model.delete(gr)
 

	
 
    def test_ValidPassword(self):
 
        validator = v.ValidPassword()
 
        self.assertEqual('lol', validator.to_python('lol'))
 
        self.assertEqual(None, validator.to_python(None))
 
        self.assertRaises(formencode.Invalid, validator.to_python, 'ąćżź')
 

	
 
    def test_ValidPasswordsMatch(self):
 
        validator = v.ValidPasswordsMatch()
 
        self.assertRaises(formencode.Invalid,
 
                    validator.to_python, {'password': 'pass',
 
                                          'password_confirmation': 'pass2'})
 

	
 
        self.assertRaises(formencode.Invalid,
 
                    validator.to_python, {'new_password': 'pass',
 
                                          'password_confirmation': 'pass2'})
 

	
 
        self.assertEqual({'new_password': 'pass',
 
                          'password_confirmation': 'pass'},
 
                    validator.to_python({'new_password': 'pass',
 
                                         'password_confirmation': 'pass'}))
 

	
 
        self.assertEqual({'password': 'pass',
 
                          'password_confirmation': 'pass'},
 
                    validator.to_python({'password': 'pass',
 
                                         'password_confirmation': 'pass'}))
 

	
 
    def test_ValidAuth(self):
 
        validator = v.ValidAuth()
 
        valid_creds = {
 
            'username': TEST_USER_REGULAR2_LOGIN,
 
            'password': TEST_USER_REGULAR2_PASS,
 
        }
 
        invalid_creds = {
 
            'username': 'err',
 
            'password': 'err',
 
        }
 
        self.assertEqual(valid_creds, validator.to_python(valid_creds))
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, invalid_creds)
 

	
 
    def test_ValidAuthToken(self):
 
        validator = v.ValidAuthToken()
 
        # this is untestable without a threadlocal
 
#        self.assertRaises(formencode.Invalid,
 
#                          validator.to_python, 'BadToken')
 
        validator
 

	
 
    def test_ValidRepoName(self):
 
        validator = v.ValidRepoName()
 

	
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, {'repo_name': ''})
 

	
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, {'repo_name': HG_REPO})
 

	
 
        gr = ReposGroupModel().create(group_name='group_test',
 
                                      group_description='desc',
 
                                      parent=None,
 
                                      owner=TEST_USER_ADMIN_LOGIN)
 
        self.assertRaises(formencode.Invalid,
 
                          validator.to_python, {'repo_name': gr.group_name})
 

	
 
        #TODO: write an error case for that ie. create a repo withinh a group
 
#        self.assertRaises(formencode.Invalid,
 
#                          validator.to_python, {'repo_name': 'some',
 
#                                                'repo_group': gr.group_id})
 

	
 
    def test_ValidForkName(self):
 
        # this uses ValidRepoName validator
 
        assert True
 

	
 
    @parameterized.expand([
0 comments (0 inline, 0 general)