changeset 2709:d2d35cf2b351 beta

RhodeCode now has a option to explicitly set forking permissions. ref #508 - changed the way permissons on users groups behave. Now explicit set on user is more important than permission set on users group
author Marcin Kuzminski <marcin@python-works.com>
date Fri, 10 Aug 2012 03:09:36 +0200
parents 9bce679a3f49
children f4ff3b5bfc42
files docs/changelog.rst rhodecode/controllers/admin/permissions.py rhodecode/controllers/admin/users.py rhodecode/controllers/admin/users_groups.py rhodecode/controllers/forks.py rhodecode/lib/auth.py rhodecode/lib/db_manage.py rhodecode/model/db.py rhodecode/model/forms.py rhodecode/model/permission.py rhodecode/model/user.py rhodecode/model/users_group.py rhodecode/templates/admin/permissions/permissions.html rhodecode/templates/admin/users/user_edit.html rhodecode/templates/admin/users_groups/users_group_edit.html rhodecode/tests/functional/test_admin_users.py rhodecode/tests/functional/test_admin_users_groups.py rhodecode/tests/functional/test_forks.py rhodecode/tests/models/test_permissions.py
diffstat 19 files changed, 658 insertions(+), 201 deletions(-) [+]
line wrap: on
line diff
--- a/docs/changelog.rst	Wed Aug 08 23:30:55 2012 +0200
+++ b/docs/changelog.rst	Fri Aug 10 03:09:36 2012 +0200
@@ -37,7 +37,7 @@
   that defines 'default' revision/branch for generating readme files
 - Implemented #509, RhodeCode enforces SSL for push/pulling if requested.
 - Import remote svn repositories to mercurial using hgsubversion  
-
+- Fixed #508 RhodeCode now has a option to explicitly set forking permissions
 
 fixes
 +++++
--- a/rhodecode/controllers/admin/permissions.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/controllers/admin/permissions.py	Fri Aug 10 03:09:36 2012 +0200
@@ -71,6 +71,15 @@
         self.create_choices = [('hg.create.none', _('Disabled')),
                                ('hg.create.repository', _('Enabled'))]
 
+        self.fork_choices = [('hg.fork.none', _('Disabled')),
+                             ('hg.fork.repository', _('Enabled'))]
+
+        # set the global template variables
+        c.perms_choices = self.perms_choices
+        c.register_choices = self.register_choices
+        c.create_choices = self.create_choices
+        c.fork_choices = self.fork_choices
+
     def index(self, format='html'):
         """GET /permissions: All items in the collection"""
         # url('permissions')
@@ -96,7 +105,8 @@
 
         _form = DefaultPermissionsForm([x[0] for x in self.perms_choices],
                                        [x[0] for x in self.register_choices],
-                                       [x[0] for x in self.create_choices])()
+                                       [x[0] for x in self.create_choices],
+                                       [x[0] for x in self.fork_choices])()
 
         try:
             form_result = _form.to_python(dict(request.POST))
@@ -107,9 +117,6 @@
                     category='success')
 
         except formencode.Invalid, errors:
-            c.perms_choices = self.perms_choices
-            c.register_choices = self.register_choices
-            c.create_choices = self.create_choices
             defaults = errors.value
 
             return htmlfill.render(
@@ -141,10 +148,8 @@
     def edit(self, id, format='html'):
         """GET /permissions/id/edit: Form to edit an existing item"""
         #url('edit_permission', id=ID)
-        c.perms_choices = self.perms_choices
-        c.register_choices = self.register_choices
-        c.create_choices = self.create_choices
 
+        #this form can only edit default user permissions
         if id == 'default':
             default_user = User.get_by_username('default')
             defaults = {'_method': 'put',
@@ -160,10 +165,14 @@
                 if p.permission.permission_name.startswith('hg.create.'):
                     defaults['default_create'] = p.permission.permission_name
 
+                if p.permission.permission_name.startswith('hg.fork.'):
+                    defaults['default_fork'] = p.permission.permission_name
+
             return htmlfill.render(
-                        render('admin/permissions/permissions.html'),
-                        defaults=defaults,
-                        encoding="UTF-8",
-                        force_defaults=True,)
+                render('admin/permissions/permissions.html'),
+                defaults=defaults,
+                encoding="UTF-8",
+                force_defaults=True,
+            )
         else:
             return redirect(url('admin_home'))
--- a/rhodecode/controllers/admin/users.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/controllers/admin/users.py	Fri Aug 10 03:09:36 2012 +0200
@@ -33,6 +33,7 @@
 from pylons.controllers.util import redirect
 from pylons.i18n.translation import _
 
+import rhodecode
 from rhodecode.lib.exceptions import DefaultUserException, \
     UserOwnsReposException
 from rhodecode.lib import helpers as h
@@ -40,14 +41,13 @@
     AuthUser
 from rhodecode.lib.base import BaseController, render
 
-import rhodecode
-from rhodecode.model.db import User, Permission, UserEmailMap
+from rhodecode.model.db import User, UserEmailMap
 from rhodecode.model.forms import UserForm
 from rhodecode.model.user import UserModel
 from rhodecode.model.meta import Session
 from rhodecode.lib.utils import action_logger
 from rhodecode.lib.compat import json
-from rhodecode.lib.utils2 import datetime_to_time
+from rhodecode.lib.utils2 import datetime_to_time, str2bool
 
 log = logging.getLogger(__name__)
 
@@ -175,9 +175,11 @@
                             .filter(UserEmailMap.user == c.user).all()
             defaults = errors.value
             e = errors.error_dict or {}
-            perm = Permission.get_by_key('hg.create.repository')
-            defaults.update({'create_repo_perm': user_model.has_perm(id, perm)})
-            defaults.update({'_method': 'put'})
+            defaults.update({
+                'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
+                'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
+                '_method': 'put'
+            })
             return htmlfill.render(
                 render('admin/users/user_edit.html'),
                 defaults=defaults,
@@ -188,7 +190,7 @@
             log.error(traceback.format_exc())
             h.flash(_('error occurred during update of user %s') \
                     % form_result.get('username'), category='error')
-        return redirect(url('users'))
+        return redirect(url('edit_user', id=id))
 
     def delete(self, id):
         """DELETE /users/id: Delete an existing item"""
@@ -198,9 +200,9 @@
         #    h.form(url('delete_user', id=ID),
         #           method='delete')
         # url('user', id=ID)
-        user_model = UserModel()
+        usr = User.get_or_404(id)
         try:
-            user_model.delete(id)
+            UserModel().delete(usr)
             Session().commit()
             h.flash(_('successfully deleted user'), category='success')
         except (UserOwnsReposException, DefaultUserException), e:
@@ -223,15 +225,19 @@
         if c.user.username == 'default':
             h.flash(_("You can't edit this user"), category='warning')
             return redirect(url('users'))
+
         c.perm_user = AuthUser(user_id=id)
         c.user.permissions = {}
         c.granted_permissions = UserModel().fill_perms(c.user)\
             .permissions['global']
         c.user_email_map = UserEmailMap.query()\
                         .filter(UserEmailMap.user == c.user).all()
+        user_model = UserModel()
         defaults = c.user.get_dict()
-        perm = Permission.get_by_key('hg.create.repository')
-        defaults.update({'create_repo_perm': UserModel().has_perm(id, perm)})
+        defaults.update({
+            'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'),
+            'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'),
+        })
 
         return htmlfill.render(
             render('admin/users/user_edit.html'),
@@ -243,28 +249,44 @@
     def update_perm(self, id):
         """PUT /users_perm/id: Update an existing item"""
         # url('user_perm', id=ID, method='put')
+        usr = User.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'))
 
-        grant_perm = request.POST.get('create_repo_perm', False)
         user_model = UserModel()
 
-        if grant_perm:
-            perm = Permission.get_by_key('hg.create.none')
-            user_model.revoke_perm(id, perm)
+        try:
+            usr.inherit_default_permissions = inherit_perms
+            Session().add(usr)
 
-            perm = Permission.get_by_key('hg.create.repository')
-            user_model.grant_perm(id, perm)
-            h.flash(_("Granted 'repository create' permission to user"),
-                    category='success')
+            if grant_create_perm:
+                user_model.revoke_perm(usr, 'hg.create.none')
+                user_model.grant_perm(usr, 'hg.create.repository')
+                h.flash(_("Granted 'repository create' permission to user"),
+                        category='success')
+            else:
+                user_model.revoke_perm(usr, 'hg.create.repository')
+                user_model.grant_perm(usr, 'hg.create.none')
+                h.flash(_("Revoked 'repository create' permission to user"),
+                        category='success')
+
+            if grant_fork_perm:
+                user_model.revoke_perm(usr, 'hg.fork.none')
+                user_model.grant_perm(usr, 'hg.fork.repository')
+                h.flash(_("Granted 'repository fork' permission to user"),
+                        category='success')
+            else:
+                user_model.revoke_perm(usr, 'hg.fork.repository')
+                user_model.grant_perm(usr, 'hg.fork.none')
+                h.flash(_("Revoked 'repository fork' permission to user"),
+                        category='success')
+
             Session().commit()
-        else:
-            perm = Permission.get_by_key('hg.create.repository')
-            user_model.revoke_perm(id, perm)
-
-            perm = Permission.get_by_key('hg.create.none')
-            user_model.grant_perm(id, perm)
-            h.flash(_("Revoked 'repository create' permission to user"),
-                    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_user', id=id))
 
     def add_email(self, id):
--- a/rhodecode/controllers/admin/users_groups.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/controllers/admin/users_groups.py	Fri Aug 10 03:09:36 2012 +0200
@@ -34,13 +34,13 @@
 
 from rhodecode.lib import helpers as h
 from rhodecode.lib.exceptions import UsersGroupsAssignedException
-from rhodecode.lib.utils2 import safe_unicode
+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.db import User, UsersGroup, Permission, UsersGroupToPerm
+from rhodecode.model.db import User, UsersGroup
 from rhodecode.model.forms import UsersGroupForm
 from rhodecode.model.meta import Session
 from rhodecode.lib.utils import action_logger
@@ -135,15 +135,20 @@
             h.flash(_('updated users group %s') % gr, category='success')
             Session().commit()
         except formencode.Invalid, errors:
+            ug_model = UsersGroupModel()
+            defaults = errors.value
             e = errors.error_dict or {}
-
-            perm = Permission.get_by_key('hg.create.repository')
-            e.update({'create_repo_perm':
-                         UsersGroupModel().has_perm(id, perm)})
+            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=errors.value,
+                defaults=defaults,
                 errors=e,
                 prefix_error=False,
                 encoding="UTF-8")
@@ -152,7 +157,7 @@
             h.flash(_('error occurred during update of users group %s') \
                     % request.POST.get('users_group_name'), category='error')
 
-        return redirect(url('users_groups'))
+        return redirect(url('edit_users_group', id=id))
 
     def delete(self, id):
         """DELETE /users_groups/id: Delete an existing item"""
@@ -162,9 +167,9 @@
         #    h.form(url('users_group', id=ID),
         #           method='delete')
         # url('users_group', id=ID)
-
+        usr_gr = UsersGroup.get_or_404(id)
         try:
-            UsersGroupModel().delete(id)
+            UsersGroupModel().delete(usr_gr)
             Session().commit()
             h.flash(_('successfully deleted users group'), category='success')
         except UsersGroupsAssignedException, e:
@@ -183,9 +188,7 @@
         """GET /users_groups/id/edit: Form to edit an existing item"""
         # url('edit_users_group', id=ID)
 
-        c.users_group = UsersGroup.get(id)
-        if not c.users_group:
-            return redirect(url('users_groups'))
+        c.users_group = UsersGroup.get_or_404(id)
 
         c.users_group.permissions = {}
         c.group_members_obj = [x.user for x in c.users_group.members]
@@ -193,10 +196,15 @@
                            c.group_members_obj]
         c.available_members = [(x.user_id, x.username) for x in
                                User.query().all()]
+        ug_model = UsersGroupModel()
         defaults = c.users_group.get_dict()
-        perm = Permission.get_by_key('hg.create.repository')
-        defaults.update({'create_repo_perm':
-                         UsersGroupModel().has_perm(c.users_group, perm)})
+        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,
@@ -208,25 +216,43 @@
         """PUT /users_perm/id: Update an existing item"""
         # url('users_group_perm', id=ID, method='put')
 
-        grant_perm = request.POST.get('create_repo_perm', False)
+        users_group = UsersGroup.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()
+
+        try:
+            users_group.inherit_default_permissions = inherit_perms
+            Session().add(users_group)
 
-        if grant_perm:
-            perm = Permission.get_by_key('hg.create.none')
-            UsersGroupModel().revoke_perm(id, perm)
+            if grant_create_perm:
+                usersgroup_model.revoke_perm(id, 'hg.create.none')
+                usersgroup_model.grant_perm(id, 'hg.create.repository')
+                h.flash(_("Granted 'repository create' permission to users group"),
+                        category='success')
+            else:
+                usersgroup_model.revoke_perm(id, 'hg.create.repository')
+                usersgroup_model.grant_perm(id, 'hg.create.none')
+                h.flash(_("Revoked 'repository create' permission to users group"),
+                        category='success')
 
-            perm = Permission.get_by_key('hg.create.repository')
-            UsersGroupModel().grant_perm(id, perm)
-            h.flash(_("Granted 'repository create' permission to user"),
-                    category='success')
+            if grant_fork_perm:
+                usersgroup_model.revoke_perm(id, 'hg.fork.none')
+                usersgroup_model.grant_perm(id, 'hg.fork.repository')
+                h.flash(_("Granted 'repository fork' permission to users group"),
+                        category='success')
+            else:
+                usersgroup_model.revoke_perm(id, 'hg.fork.repository')
+                usersgroup_model.grant_perm(id, 'hg.fork.none')
+                h.flash(_("Revoked 'repository fork' permission to users group"),
+                        category='success')
 
             Session().commit()
-        else:
-            perm = Permission.get_by_key('hg.create.repository')
-            UsersGroupModel().revoke_perm(id, perm)
+        except Exception:
+            log.error(traceback.format_exc())
+            h.flash(_('An error occurred during permissions saving'),
+                    category='error')
 
-            perm = Permission.get_by_key('hg.create.none')
-            UsersGroupModel().grant_perm(id, perm)
-            h.flash(_("Revoked 'repository create' permission to user"),
-                    category='success')
-            Session().commit()
         return redirect(url('edit_users_group', id=id))
--- a/rhodecode/controllers/forks.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/controllers/forks.py	Fri Aug 10 03:09:36 2012 +0200
@@ -35,7 +35,8 @@
 
 from rhodecode.lib.helpers import Page
 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
-    NotAnonymous, HasRepoPermissionAny
+    NotAnonymous, HasRepoPermissionAny, HasPermissionAllDecorator,\
+    HasPermissionAnyDecorator
 from rhodecode.lib.base import BaseRepoController, render
 from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User
 from rhodecode.model.repo import RepoModel
@@ -123,6 +124,7 @@
         return render('/forks/forks.html')
 
     @NotAnonymous()
+    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def fork(self, repo_name):
@@ -146,6 +148,7 @@
         )
 
     @NotAnonymous()
+    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
     @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                    'repository.admin')
     def fork_create(self, repo_name):
--- a/rhodecode/lib/auth.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/lib/auth.py	Fri Aug 10 03:09:36 2012 +0200
@@ -350,6 +350,7 @@
             log.debug('Auth User lookup by USER NAME %s' % self.username)
             dbuser = login_container_auth(self.username)
             if dbuser is not None:
+                log.debug('filling all attributes to object')
                 for k, v in dbuser.get_dict().items():
                     setattr(self, k, v)
                 self.set_authenticated()
--- a/rhodecode/lib/db_manage.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/lib/db_manage.py	Fri Aug 10 03:09:36 2012 +0200
@@ -513,27 +513,32 @@
     def populate_default_permissions(self):
         log.info('creating default user permissions')
 
-        default_user = self.sa.query(User)\
-        .filter(User.username == 'default').scalar()
+        default_user = User.get_by_username('default')
 
         reg_perm = UserToPerm()
         reg_perm.user = default_user
         reg_perm.permission = self.sa.query(Permission)\
-        .filter(Permission.permission_name == 'hg.register.manual_activate')\
-        .scalar()
+         .filter(Permission.permission_name == 'hg.register.manual_activate')\
+         .scalar()
+        self.sa.add(reg_perm)
 
         create_repo_perm = UserToPerm()
         create_repo_perm.user = default_user
         create_repo_perm.permission = self.sa.query(Permission)\
-        .filter(Permission.permission_name == 'hg.create.repository')\
-        .scalar()
+         .filter(Permission.permission_name == 'hg.create.repository')\
+         .scalar()
+        self.sa.add(create_repo_perm)
+
+        default_fork_perm = UserToPerm()
+        default_fork_perm.user = default_user
+        default_fork_perm.permission = self.sa.query(Permission)\
+         .filter(Permission.permission_name == 'hg.fork.repository')\
+         .scalar()
+        self.sa.add(default_fork_perm)
 
         default_repo_perm = UserToPerm()
         default_repo_perm.user = default_user
         default_repo_perm.permission = self.sa.query(Permission)\
-        .filter(Permission.permission_name == 'repository.read')\
-        .scalar()
-
-        self.sa.add(reg_perm)
-        self.sa.add(create_repo_perm)
+         .filter(Permission.permission_name == 'repository.read')\
+         .scalar()
         self.sa.add(default_repo_perm)
--- a/rhodecode/model/db.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/model/db.py	Fri Aug 10 03:09:36 2012 +0200
@@ -294,6 +294,7 @@
     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')
@@ -504,6 +505,7 @@
     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')
@@ -1084,6 +1086,8 @@
         ('hg.admin', _('RhodeCode Administrator')),
         ('hg.create.none', _('Repository creation disabled')),
         ('hg.create.repository', _('Repository creation enabled')),
+        ('hg.fork.none', _('Repository forking disabled')),
+        ('hg.fork.repository', _('Repository forking enabled')),
         ('hg.register.none', _('Register disabled')),
         ('hg.register.manual_activate', _('Register new user with RhodeCode '
                                           'with manual activation')),
@@ -1092,6 +1096,24 @@
                                         'with auto activation')),
     ]
 
+    # 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)
--- a/rhodecode/model/forms.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/model/forms.py	Fri Aug 10 03:09:36 2012 +0200
@@ -274,7 +274,8 @@
     return _ApplicationUiSettingsForm
 
 
-def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
+def DefaultPermissionsForm(perms_choices, register_choices, create_choices,
+                           fork_choices):
     class _DefaultPermissionsForm(formencode.Schema):
         allow_extra_fields = True
         filter_extra_fields = True
@@ -283,6 +284,7 @@
         default_perm = v.OneOf(perms_choices)
         default_register = v.OneOf(register_choices)
         default_create = v.OneOf(create_choices)
+        default_fork = v.OneOf(fork_choices)
 
     return _DefaultPermissionsForm
 
--- a/rhodecode/model/permission.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/model/permission.py	Fri Aug 10 03:09:36 2012 +0200
@@ -77,8 +77,8 @@
                                 form_result['perm_user_name']).scalar()
         u2p = self.sa.query(UserToPerm).filter(UserToPerm.user ==
                                                perm_user).all()
-        if len(u2p) != 3:
-            raise Exception('Defined: %s should be 3  permissions for default'
+        if len(u2p) != 4:
+            raise Exception('Defined: %s should be 4  permissions for default'
                             ' user. This should not happen please verify'
                             ' your database' % len(u2p))
 
@@ -100,6 +100,11 @@
                                         form_result['default_create'])
                     self.sa.add(p)
 
+                elif p.permission.permission_name.startswith('hg.fork.'):
+                    p.permission = self.get_permission_by_name(
+                                        form_result['default_fork'])
+                    self.sa.add(p)
+
             _def_name = form_result['default_perm'].split('repository.')[-1]
             #stage 2 update all default permissions for repos if checked
             if form_result['overwrite_default'] == True:
--- a/rhodecode/model/user.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/model/user.py	Fri Aug 10 03:09:36 2012 +0200
@@ -25,7 +25,7 @@
 
 import logging
 import traceback
-
+import itertools
 from pylons import url
 from pylons.i18n.translation import _
 
@@ -45,17 +45,7 @@
 
 log = logging.getLogger(__name__)
 
-
-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,
-}
+PERM_WEIGHTS = Permission.PERM_WEIGHTS
 
 
 class UserModel(BaseModel):
@@ -432,11 +422,11 @@
             return user
 
         #==================================================================
-        # set default permissions first for repositories and groups
+        # SET DEFAULTS GLOBAL, REPOS, REPOS GROUPS
         #==================================================================
         uid = user.user_id
 
-        # default global permissions
+        # default global permissions taken fron the default user
         default_global_perms = self.sa.query(UserToPerm)\
             .filter(UserToPerm.user_id == default_user_id)
 
@@ -464,25 +454,89 @@
             p = perm.Permission.permission_name
             user.permissions[GK][rg_k] = p
 
-        #==================================================================
-        # overwrite defaults with user permissions if any found
-        #==================================================================
+        #======================================================================
+        # !! 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 global permissions
+        # USER GROUPS comes first
+        # users 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)\
+            .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()
 
-        for perm in user_perms:
-            user.permissions[GLOBAL].add(perm.permission.permission_name)
+        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)
+
+        #======================================================================
+        # !! REPO PERMISSIONS !!
+        #======================================================================
+        #======================================================================
+        # check if user is part of user groups for this repository and
+        # fill in (or NOT replace with higher `or 1` permissions
+        #======================================================================
+        # users group for repositories permissions
+        user_repo_perms_from_users_groups = \
+         self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
+            .join((Repository, UsersGroupRepoToPerm.repository_id ==
+                   Repository.repo_id))\
+            .join((Permission, UsersGroupRepoToPerm.permission_id ==
+                   Permission.permission_id))\
+            .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id ==
+                   UsersGroupMember.users_group_id))\
+            .filter(UsersGroupMember.user_id == uid)\
+            .all()
+
+        for perm in user_repo_perms_from_users_groups:
+            r_k = perm.UsersGroupRepoToPerm.repository.repo_name
+            p = perm.Permission.permission_name
+            cur_perm = user.permissions[RK][r_k]
+            # overwrite permission only if it's greater than permission
+            # given from other sources
+            if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm] or 1:  # disable check
+                user.permissions[RK][r_k] = p
 
         # user explicit permissions for repositories
         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()
+            .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:
             # set admin if owner
@@ -493,40 +547,6 @@
                 p = perm.Permission.permission_name
             user.permissions[RK][r_k] = p
 
-        # USER GROUP
-        #==================================================================
-        # check if user is part of user groups for this repository and
-        # fill in (or replace with higher) permissions
-        #==================================================================
-
-        # users group global
-        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).all()
-
-        for perm in user_perms_from_users_groups:
-            user.permissions[GLOBAL].add(perm.permission.permission_name)
-
-        # users group for repositories permissions
-        user_repo_perms_from_users_groups = \
-         self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
-         .join((Repository, UsersGroupRepoToPerm.repository_id == Repository.repo_id))\
-         .join((Permission, UsersGroupRepoToPerm.permission_id == Permission.permission_id))\
-         .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == UsersGroupMember.users_group_id))\
-         .filter(UsersGroupMember.user_id == uid)\
-         .all()
-
-        for perm in user_repo_perms_from_users_groups:
-            r_k = perm.UsersGroupRepoToPerm.repository.repo_name
-            p = perm.Permission.permission_name
-            cur_perm = user.permissions[RK][r_k]
-            # overwrite permission only if it's greater than permission
-            # given from other sources
-            if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
-                user.permissions[RK][r_k] = p
-
         # REPO GROUP
         #==================================================================
         # get access for this user for repos group and override defaults
@@ -574,10 +594,7 @@
         return user
 
     def has_perm(self, user, perm):
-        if not isinstance(perm, Permission):
-            raise Exception('perm needs to be an instance of Permission class '
-                            'got %s instead' % type(perm))
-
+        perm = self._get_perm(perm)
         user = self._get_user(user)
 
         return UserToPerm.query().filter(UserToPerm.user == user)\
--- a/rhodecode/model/users_group.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/model/users_group.py	Fri Aug 10 03:09:36 2012 +0200
@@ -165,10 +165,8 @@
             .filter(UsersGroupToPerm.permission == perm).scalar() is not None
 
     def grant_perm(self, users_group, perm):
-        if not isinstance(perm, Permission):
-            raise Exception('perm needs to be an instance of Permission class')
-
         users_group = self.__get_users_group(users_group)
+        perm = self._get_perm(perm)
 
         # if this permission is already granted skip it
         _perm = UsersGroupToPerm.query()\
--- a/rhodecode/templates/admin/permissions/permissions.html	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/templates/admin/permissions/permissions.html	Fri Aug 10 03:09:36 2012 +0200
@@ -37,7 +37,7 @@
                 </div>
             </div>
 			<div class="field">
-				<div class="label label-select">
+				<div class="label">
 					<label for="default_perm">${_('Repository permission')}:</label>
 				</div>
 				<div class="select">
@@ -66,7 +66,14 @@
 					${h.select('default_create','',c.create_choices)}
 				</div>
              </div>
-
+             <div class="field">
+                <div class="label">
+                    <label for="default_fork">${_('Repository forking')}:</label>
+                </div>
+                <div class="select">
+                    ${h.select('default_fork','',c.fork_choices)}
+                </div>
+             </div>
 	        <div class="buttons">
 	        ${h.submit('set',_('set'),class_="ui-btn large")}
 	        </div>
--- a/rhodecode/templates/admin/users/user_edit.html	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/templates/admin/users/user_edit.html	Fri Aug 10 03:09:36 2012 +0200
@@ -144,12 +144,32 @@
         <div class="fields">
              <div class="field">
                 <div class="label label-checkbox">
+                    <label for="inherit_permissions">${_('Inherit default permissions')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('inherit_default_permissions',value=True)}
+                </div>
+                <span class="help-block">${h.literal(_('Select to inherit permissions from %s settings. '
+                                             'With this selected below options does not have any action') % h.link_to('default', url('edit_permission', id='default')))}</span>
+             </div>
+             <div id="inherit_overlay" style="${'opacity:0.3' if c.user.inherit_default_permissions else ''}" >        
+             <div class="field">
+                <div class="label label-checkbox">
                     <label for="create_repo_perm">${_('Create repositories')}:</label>
                 </div>
                 <div class="checkboxes">
                     ${h.checkbox('create_repo_perm',value=True)}
                 </div>
              </div>
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label for="fork_repo_perm">${_('Fork repositories')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('fork_repo_perm',value=True)}
+                </div>
+             </div>
+             </div>             
             <div class="buttons">
               ${h.submit('save',_('Save'),class_="ui-btn large")}
               ${h.reset('reset',_('Reset'),class_="ui-btn large")}
--- a/rhodecode/templates/admin/users_groups/users_group_edit.html	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/templates/admin/users_groups/users_group_edit.html	Fri Aug 10 03:09:36 2012 +0200
@@ -105,12 +105,32 @@
         <div class="fields">
              <div class="field">
                 <div class="label label-checkbox">
+                    <label for="inherit_permissions">${_('Inherit default permissions')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('inherit_default_permissions',value=True)}
+                </div>
+                <span class="help-block">${h.literal(_('Select to inherit permissions from %s settings. '
+                                             'With this selected below options does not have any action') % h.link_to('default', url('edit_permission', id='default')))}</span>
+             </div>        
+             <div id="inherit_overlay" style="${'opacity:0.3' if c.users_group.inherit_default_permissions else ''}" >
+             <div class="field">
+                <div class="label label-checkbox">
                     <label for="create_repo_perm">${_('Create repositories')}:</label>
                 </div>
                 <div class="checkboxes">
                     ${h.checkbox('create_repo_perm',value=True)}
                 </div>
              </div>
+             <div class="field">
+                <div class="label label-checkbox">
+                    <label for="fork_repo_perm">${_('Fork repositories')}:</label>
+                </div>
+                <div class="checkboxes">
+                    ${h.checkbox('fork_repo_perm',value=True)}
+                </div>
+             </div>
+             </div>          
             <div class="buttons">
               ${h.submit('save',_('Save'),class_="ui-btn large")}
               ${h.reset('reset',_('Reset'),class_="ui-btn large")}
--- a/rhodecode/tests/functional/test_admin_users.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/tests/functional/test_admin_users.py	Fri Aug 10 03:09:36 2012 +0200
@@ -6,6 +6,7 @@
 from rhodecode.model.user import UserModel
 from rhodecode.model import validators
 from rhodecode.lib import helpers as h
+from rhodecode.model.meta import Session
 
 
 class TestAdminUsersController(TestController):
@@ -172,45 +173,118 @@
         perm_none = Permission.get_by_key('hg.create.none')
         perm_create = Permission.get_by_key('hg.create.repository')
 
-        user = User.get_by_username(TEST_USER_REGULAR_LOGIN)
+        user = UserModel().create_or_update(username='dummy', password='qwe',
+                                            email='dummy', firstname='a',
+                                            lastname='b')
+        Session().commit()
+        uid = user.user_id
 
-        #User should have None permission on creation repository
-        self.assertEqual(UserModel().has_perm(user, perm_none), False)
-        self.assertEqual(UserModel().has_perm(user, perm_create), False)
+        try:
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(user, perm_none), False)
+            self.assertEqual(UserModel().has_perm(user, perm_create), False)
 
-        response = self.app.post(url('user_perm', id=user.user_id),
-                                 params=dict(_method='put',
-                                             create_repo_perm=True))
+            response = self.app.post(url('user_perm', id=uid),
+                                     params=dict(_method='put',
+                                                 create_repo_perm=True))
+
+            perm_none = Permission.get_by_key('hg.create.none')
+            perm_create = Permission.get_by_key('hg.create.repository')
 
-        perm_none = Permission.get_by_key('hg.create.none')
-        perm_create = Permission.get_by_key('hg.create.repository')
-
-        user = User.get_by_username(TEST_USER_REGULAR_LOGIN)
-        #User should have None permission on creation repository
-        self.assertEqual(UserModel().has_perm(user, perm_none), False)
-        self.assertEqual(UserModel().has_perm(user, perm_create), True)
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(uid, perm_none), False)
+            self.assertEqual(UserModel().has_perm(uid, perm_create), True)
+        finally:
+            UserModel().delete(uid)
+            Session().commit()
 
     def test_revoke_perm_create_repo(self):
         self.log_user()
         perm_none = Permission.get_by_key('hg.create.none')
         perm_create = Permission.get_by_key('hg.create.repository')
 
-        user = User.get_by_username(TEST_USER_REGULAR2_LOGIN)
+        user = UserModel().create_or_update(username='dummy', password='qwe',
+                                            email='dummy', firstname='a',
+                                            lastname='b')
+        Session().commit()
+        uid = user.user_id
+
+        try:
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(user, perm_none), False)
+            self.assertEqual(UserModel().has_perm(user, perm_create), False)
+
+            response = self.app.post(url('user_perm', id=uid),
+                                     params=dict(_method='put'))
+
+            perm_none = Permission.get_by_key('hg.create.none')
+            perm_create = Permission.get_by_key('hg.create.repository')
 
-        #User should have None permission on creation repository
-        self.assertEqual(UserModel().has_perm(user, perm_none), False)
-        self.assertEqual(UserModel().has_perm(user, perm_create), False)
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(uid, perm_none), True)
+            self.assertEqual(UserModel().has_perm(uid, perm_create), False)
+        finally:
+            UserModel().delete(uid)
+            Session().commit()
+
+    def test_add_perm_fork_repo(self):
+        self.log_user()
+        perm_none = Permission.get_by_key('hg.fork.none')
+        perm_fork = Permission.get_by_key('hg.fork.repository')
+
+        user = UserModel().create_or_update(username='dummy', password='qwe',
+                                            email='dummy', firstname='a',
+                                            lastname='b')
+        Session().commit()
+        uid = user.user_id
+
+        try:
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(user, perm_none), False)
+            self.assertEqual(UserModel().has_perm(user, perm_fork), False)
 
-        response = self.app.post(url('user_perm', id=user.user_id),
-                                 params=dict(_method='put'))
+            response = self.app.post(url('user_perm', id=uid),
+                                     params=dict(_method='put',
+                                                 create_repo_perm=True))
+
+            perm_none = Permission.get_by_key('hg.create.none')
+            perm_create = Permission.get_by_key('hg.create.repository')
+
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(uid, perm_none), False)
+            self.assertEqual(UserModel().has_perm(uid, perm_create), True)
+        finally:
+            UserModel().delete(uid)
+            Session().commit()
+
+    def test_revoke_perm_fork_repo(self):
+        self.log_user()
+        perm_none = Permission.get_by_key('hg.fork.none')
+        perm_fork = Permission.get_by_key('hg.fork.repository')
 
-        perm_none = Permission.get_by_key('hg.create.none')
-        perm_create = Permission.get_by_key('hg.create.repository')
+        user = UserModel().create_or_update(username='dummy', password='qwe',
+                                            email='dummy', firstname='a',
+                                            lastname='b')
+        Session().commit()
+        uid = user.user_id
+
+        try:
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(user, perm_none), False)
+            self.assertEqual(UserModel().has_perm(user, perm_fork), False)
 
-        user = User.get_by_username(TEST_USER_REGULAR2_LOGIN)
-        #User should have None permission on creation repository
-        self.assertEqual(UserModel().has_perm(user, perm_none), True)
-        self.assertEqual(UserModel().has_perm(user, perm_create), False)
+            response = self.app.post(url('user_perm', id=uid),
+                                     params=dict(_method='put'))
+
+            perm_none = Permission.get_by_key('hg.create.none')
+            perm_create = Permission.get_by_key('hg.create.repository')
+
+            #User should have None permission on creation repository
+            self.assertEqual(UserModel().has_perm(uid, perm_none), True)
+            self.assertEqual(UserModel().has_perm(uid, perm_create), False)
+        finally:
+            UserModel().delete(uid)
+            Session().commit()
 
     def test_edit_as_xml(self):
         response = self.app.get(url('formatted_edit_user', id=1, format='xml'))
--- a/rhodecode/tests/functional/test_admin_users_groups.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/tests/functional/test_admin_users_groups.py	Fri Aug 10 03:09:36 2012 +0200
@@ -65,27 +65,48 @@
         users_group_name = TEST_USERS_GROUP + 'another2'
         response = self.app.post(url('users_groups'),
                                  {'users_group_name': users_group_name,
-                                  'active':True})
+                                  'active': True})
         response.follow()
 
         ug = UsersGroup.get_by_group_name(users_group_name)
         self.checkSessionFlash(response,
                                'created users 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)
         p = Permission.get_by_key('hg.create.repository')
-        # check if user has this perm
+        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 = [[x.__dict__['users_group_id'],
-                  x.__dict__['permission_id'],] for x in perms]
+
         self.assertEqual(
-            perms,
-            [[ug.users_group_id, p.permission_id]]
+            [[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)
+        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()
+
+        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 !
@@ -101,8 +122,77 @@
         p = Permission.get_by_key('hg.create.repository')
         perms = UsersGroupToPerm.query()\
             .filter(UsersGroupToPerm.users_group_id == ugid).all()
-        perms = [[x.__dict__['users_group_id'],
-                  x.__dict__['permission_id'],] for x in perms]
+        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'
+        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)
+        self.checkSessionFlash(response,
+                               'created users 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)
+        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()
+
+        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)
+        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()
+
+        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)
+        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 ==
+                                   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 = [[x.users_group_id,
+                  x.permission_id, ] for x in perms]
         self.assertEqual(
             perms,
             []
--- a/rhodecode/tests/functional/test_forks.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/tests/functional/test_forks.py	Fri Aug 10 03:09:36 2012 +0200
@@ -3,6 +3,7 @@
 from rhodecode.model.db import Repository
 from rhodecode.model.repo import RepoModel
 from rhodecode.model.user import UserModel
+from rhodecode.model.meta import Session
 
 
 class TestForksController(TestController):
@@ -14,11 +15,11 @@
             username=self.username, password=self.password,
             email=u'fork_king@rhodecode.org', firstname=u'u1', lastname=u'u1'
         )
-        self.Session.commit()
+        Session().commit()
 
     def tearDown(self):
-        self.Session.delete(self.u1)
-        self.Session.commit()
+        Session().delete(self.u1)
+        Session().commit()
 
     def test_index(self):
         self.log_user()
@@ -28,6 +29,20 @@
 
         self.assertTrue("""There are no forks yet""" in response.body)
 
+    def test_no_permissions_to_fork(self):
+        usr = self.log_user(TEST_USER_REGULAR_LOGIN,
+                            TEST_USER_REGULAR_PASS)['user_id']
+        user_model = UserModel()
+        user_model.revoke_perm(usr, 'hg.fork.repository')
+        user_model.grant_perm(usr, 'hg.fork.none')
+        u = UserModel().get(usr)
+        u.inherit_default_permissions = False
+        Session().commit()
+        # try create a fork
+        repo_name = HG_REPO
+        self.app.post(url(controller='forks', action='fork_create',
+                          repo_name=repo_name), {}, status=403)
+
     def test_index_with_fork_hg(self):
         self.log_user()
 
@@ -107,7 +122,7 @@
                 'forked %s repository as %s' % (repo_name, fork_name))
 
         #test if the fork was created in the database
-        fork_repo = self.Session.query(Repository)\
+        fork_repo = Session().query(Repository)\
             .filter(Repository.repo_name == fork_name).one()
 
         self.assertEqual(fork_repo.repo_name, fork_name)
@@ -125,7 +140,7 @@
         usr = self.log_user(self.username, self.password)['user_id']
         repo_name = HG_REPO
 
-        forks = self.Session.query(Repository)\
+        forks = Session().query(Repository)\
             .filter(Repository.fork_id != None)\
             .all()
         self.assertEqual(1, len(forks))
@@ -134,7 +149,7 @@
         RepoModel().grant_user_permission(repo=forks[0],
                                           user=usr,
                                           perm='repository.read')
-        self.Session.commit()
+        Session().commit()
 
         response = self.app.get(url(controller='forks', action='forks',
                                     repo_name=repo_name))
@@ -145,7 +160,7 @@
         usr = self.log_user(self.username, self.password)['user_id']
         repo_name = HG_REPO
 
-        forks = self.Session.query(Repository)\
+        forks = Session().query(Repository)\
             .filter(Repository.fork_id != None)\
             .all()
         self.assertEqual(1, len(forks))
@@ -153,7 +168,7 @@
         # set none
         RepoModel().grant_user_permission(repo=forks[0],
                                           user=usr, perm='repository.none')
-        self.Session.commit()
+        Session().commit()
         # fork shouldn't be there
         response = self.app.get(url(controller='forks', action='forks',
                                     repo_name=repo_name))
--- a/rhodecode/tests/models/test_permissions.py	Wed Aug 08 23:30:55 2012 +0200
+++ b/rhodecode/tests/models/test_permissions.py	Fri Aug 10 03:09:36 2012 +0200
@@ -36,6 +36,10 @@
             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',
@@ -48,6 +52,7 @@
             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)
@@ -126,10 +131,11 @@
         self.assertEqual(a1_auth.permissions['repositories_groups'],
                          perms['repositories_groups'])
 
-    def test_propagated_permission_from_users_group(self):
+    def test_propagated_permission_from_users_group_by_explicit_perms_exist(self):
         # make group
         self.ug1 = UsersGroupModel().create('G1')
         # add user to group
+
         UsersGroupModel().add_user_to_group(self.ug1, self.u1)
 
         # set permission to lower
@@ -140,11 +146,12 @@
         self.assertEqual(u1_auth.permissions['repositories'][HG_REPO],
                          new_perm)
 
-        # grant perm for group this should override permission from user
-        new_perm = 'repository.write'
+        # 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)
+                                                 perm=new_perm_gr)
         # check perms
         u1_auth = AuthUser(user_id=self.u1.user_id)
         perms = {
@@ -158,6 +165,31 @@
         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')
+        # add user to group
+
+        UsersGroupModel().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')
@@ -315,3 +347,92 @@
         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']))
+
+    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']))
+
+    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']))
+
+    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']))
+